Allowing Wordpress updates to actually work via SSH

Submitted by davidc on Fri, 11/09/2020 - 17:25

In a world where FTP has finally been turned off by most ISPs, Wordpress allegedly supports SSH2 for upgrades instead, using FS_METHOD ssh2. However it fails to work in any real-world scenario because it assumes the filesystem paths on the remote host are the same as on the local filesystem.

This obviously fails with pretty much any ISP on earth as the users are chroot()ed, so a directory that was once perhaps /home/david/www.davidc.net would in fact be just /www.davidc.net when accessed over SFTP.

Symptoms are errors like "Update Failed: Plugin update failed." and "Update Failed: Unable to locate WordPress content directory (wp-content)."

Uneducated🔗 answers🔗 across🔗 the🔗 Internet🔗 suggest that you fix this by defining the FTP_BASE constant, but such suggestions have clearly never been tested. FTP_BASE is only used for FTP - specifically, for any FS_METHOD beginning with "ftp". "ssh2" does not begin with "ftp" so FTP_BASE and related configuration variables are completely ignored. Don't believe me? Look at the source - that's the only place in the entire codebase that FTP_BASE is mentioned.

Until Wordpress fixes this glaring disconnect from reality, you can get it to use the existing constants by editing that function. In file wp-admin/includes/class-wp-filesystem-base.php in the function find_folder, on line 180 of the current version (may change in future), amend:

                if ( stripos( $this->method, 'ftp' ) !== false ) {

to

                if ( stripos( $this->method, 'ftp' ) !== false || $this->method == 'ssh2' ) {

You can then define FTP_BASE, FTP_CONTENT_DIR and FTP_PLUGIN_DIR, and it will actually work like the way the idiots on the internet claim it has worked all along.

Typically you need to define both FTP_BASE and FTP_CONTENT_DIR as there is something else in the code that isn't smart enough to figure out that FTP_CONTENT_DIR should default to FTP_BASE/wp-content. I do not have the energy to waste more time on this awful code so I am done troubleshooting it for now.

Remember to omit trailing slashes from all of these directories or it will still fail.

SFTP bug

There is also a bug in wp-admin/includes/class-wp-filesystem-ssh2.php that causes SFTP URLs to be invalid. Allegedly this is a bug in PHP rather than Wordpress, but given that users are generally far less able to change their hosting provider's PHP version than their Wordpress code, I can't fathom why Wordpress won't put in a workaround.

In function sftp_path around line 203, change:

                return 'ssh2.sftp://' . $this->sftp_link . '/' . ltrim( $path, '/' );

to

                return 'ssh2.sftp://' . intval($this->sftp_link) . '/' . ltrim( $path, '/' );

You will need to reapply this patch every time you update Wordpress, since this bug has been around since at least 2015 and still hasn't been fixed by Wordpress. Not their fault - so what? They could trivially fix it to make their product work for their actual users, who don't give a toss about their conceit or about who is technically in the right.