WordPress asking for FTP connection information when updating plugins

This morning I saw that a few plugins I used had a new version and wanted to update them. I do this quite regularly on all my webpages. This time instead of seeing the update progress, I was presented a web page where I was asked to enter some FTP information:

WordPress Update Plugin FTP info

There could be two reasons for this:

  1. You want to be updating through FTP/SFTP but no credentials are added to wp_config.php
  2. You want to the updates to be directly done on the file system but WordPress cannot write to the filesystem

For the first one, the fix is easy. You just need to add your credentials to wp_config.php:

define('FTP_HOST', 'myhostname');
define('FTP_USER', 'myusername');
define('FTP_PASS', 'mypassword');

Once the file is updated, WordPress should be able to update itself, plugins and themes without asking for credentials.

Now, if like me you do not want to use FTP or SFTP but want WordPress to directly write the files to the server filesystem, you need to make sure that the user used to run WordPress has write access to the wp-content directory.

First you need to figure out which user is being used to run WordPress. The easiest way to do it (assuming you are on a Unix/Linux/Mac system) is to write a short PHP script which calls the whoami command. For this create a file called checkuser.php in the root folder of your webserver (e.g. /var/www/vhosts/benohead.com/httpdocs/checkuser.php) with the following contents:

<?php echo "user=".exec("whoami")."<br/>"; ?>

This will write something like (when you go to http://yourwebsite/checkuser.pnp):

user=www-data

So your web user is www-data.

If you cannot use whoami, another way to do it is to create a file info.php with the following contents:

<?php phpinfo(); ?>

And when you go to http://yourwebsite/info.php and there should be some entry showing you the web user (search e.g. for “APACHE_RUN_USER” or “User/Group”).

Now you need to give this user the rights to wp-content. There are a few ways to do it:

Give it the ownership of the files in wp-content e.g.:

chown -R www-data /var/www/vhosts/benohead.com/httpdocs/wp-content

Or make sure that this user belongs to the group owning wp-content and its children and give write access to the group:

chmod -R g+w /var/www/vhosts/benohead.com/httpdocs/wp-content

Now the user should have write access.

If it still doesn’t work, we’ll need to gather more info in checkuser.php:

<?php

echo "user=".exec("whoami")."<br/>";
echo "getmyuid=".getmyuid()."<br/>";

$context="/var/www/vhosts/benohead.com/httpdocs/wp-content/plugins/";
               
$temp_file_name = $context . 'temp-write-test-' . time();
echo "temp_file_name=".$temp_file_name."<br/>";
                
$temp_handle = @fopen($temp_file_name, 'w');
echo "temp_handle=".$temp_handle."<br/>";
                
if ( $temp_handle ) {
    echo "fileowner=".@fileowner($temp_file_name)."<br/>";
                        
     if ( getmyuid() == @fileowner($temp_file_name) )
         $method = 'direct';    
     @fclose($temp_handle);
     @unlink($temp_file_name);
}

echo "method=".$method."<br/>";
?>

This basically performs the same check as wordpress to determine whether the filesystem can be written to directly.

When you go to http://yourwebsite/checkuser.php, you should now see more info e.g.:

user=www-data
getmyuid=33
temp_file_name=/var/www/vhosts/benohead.com/httpdocs/wp-content/plugins/temp-write-test-1387703780
temp_handle=Resource id #4
fileowner=33
method=direct

If getmyuid and fileowner have the same value and method is direct, this means that WordPress has already seen that the filesystem is directly writeable. If they two values are different and method is empty (or if you only see the first few lines above), then you need to check the ownership of the directory again.

The problem could be that the getmyuid() function used by WordPress does not actually return the uid of the user running the script but the uid of the user owning the file being run. So you might need to issue the chown command above not only for wp-content but for all files (or at least for ./wp-admin/update.php).

If the ouput of checkuser.php is fine but it still doesn’t work, the problem might be that WordPress does figure out it can write directly but is forced to use FTP. You can check this by updating the function used to determine the filesystem method. It’s called get_filesystem_method and is located in ./wp-admin/includes/file.php.

Search for the following line:

return apply_filters('filesystem_method', $method, $args);

and replace it by:

# return apply_filters('filesystem_method', $method, $args);
echo "method before filters = ".$method."<br/>";
$method = apply_filters('filesystem_method', $method, $args);
echo "method after filters = ".$method."<br/>";
return $method;

Then try to update WordPress again. You should see two additional lines at the top e.g.:

method before filters = direct
method after filters = ftpext

The first one shows the method WordPress has determined it could use. The second one is the final method to be used after applying all filters. In this case shown above, you see that WordPress figured out it can use the direct method but some filter replaced it by the FTP method.

So then you just need to go to your WordPress root directory and search for files defining a filesystem_method filter e.g.:

# grep -R "add_filter.*filesystem_method" *
wp-config.php:	add_filter('filesystem_method', create_function('$a', 'return "direct";' ));
wp-config.php:	add_filter('filesystem_method', create_function('$a', 'return "ftpext";' ));

Now you see that two filters are defined in wp-config.php: one forcing the direct method and one forcing the FTP method. So to fix it, you just need to edit wp-config.php and remove the following lines:

if(is_admin()) {
        add_filter('filesystem_method', create_function('$a', 'return "ftpext";' ));
        define( 'FS_CHMOD_DIR', 0755 );
}

These lines seem to have been automatically added by Plesk in my case. Yesterday, I switched off the automatic WordPress updates in Plesk and it probably inserted these lines. What’s strange is that I made the same change in Plesk for 7 other sites and none of them had this problem…

One thought on “WordPress asking for FTP connection information when updating plugins

  1. Hi.

    I had a problem with a client trying to update wordpress themes. I tried disabling web application firewall, ftp user was right and had write permissions (it´s used to update web contents) so in my case, finally I believe that was a firewall problem, but I didn´t know ip ranges where wordpress try to update your web content.

    I advice to client opening 21 port for wordpress ranges or they should try to update manually.

    Regards,

Leave a Reply

Your email address will not be published. Required fields are marked *