At some point in your WordPress admin career and ESPECIALLY if you are in the business of migrating websites from one server to another you will EVENTUALLY encounter this error message when attempting to add images to your media library:
“<image-name> has failed to upload due to an error. The uploaded file could not be moved to wp-content/rest-of-path-here”
An additional side effect of this same error is that fact that you are NOT able to automatically update existing plugins OR add new ones. When you try to add a new plugin (for example), WordPress will gracefully present you with an FTP credentials screen so that you can manually upload the new plugin. So…..
WHY IS THIS HAPPENING?
In MOST instances, (especially in the case of a MIGRATED website which was already running without issues on another webserver) what is happening is that WordPress passes off the FETCHING (or uploading) of the requested image to the web server process on which your website resides and it happily retrieves the image.jpg from your harddrive and uploads to temporary memory of the server THEN tries to commit the file into storage of the WordPress media library (which is most often /wp-content/uploads/<year>/<mo>). This of course is where the error occurs. The account that actually RETRIEVES the file from your computer is the Apache service account and many times the NOBODY account (yes, that IS the real name of the account) on the server itself. Since that particular account has NO OWNERSHIP or rights to the /wp-content/uploads/<year>/<mo> folder… you get the nice error message indicating there was an issue placing the image in that particular folder. THIS IS BY DESIGN PEOPLE… and it means your web server is simply enforcing the security parameters it is aware of…. Which is a good thing!
SOME REALLY BAD ADVICE
So like any other good WordPress admin and to try and resolve this issue, you copy – paste – and Google. What you will find however should not only SHOCK you but should make the hair on your security-conscience neck stand up! 9 out of 10 “recommendations” on how to resolve this problem involve setting the permissions on your /wp-content/uploads folder to 777!!! … to that I say NO – NO – NO! If you’re going to do that you might as well change the password to your “admin” account to 12345 as well!
SO LETS INSTEAD ACTUALLY FIX THE ISSUE… THE PROPER WAY
STEP 1: Find out which account on your server is the Apache Service Account – Unfortunately, this part is not always easy for those with a shared hosting account and NO shell (sometimes called SSH) access to their site. UPDATE: See the link provided below by jervisbay in the comments section on how to fix this issue in a shared hosting environment. Thx jervisbay! The intimidation factor is that shell access is a basic command line interface… you know, the old black screen with white text and a command prompt… YUCK! However, if you DON’T have this type of access… just email your hosting support team with this simple question…What is the name of my website’s Apache Service Account? You might also want to say in your email that you are trying to set the proper permissions on your WordPress installation and that should help give them some context as to your request.
Now… if you DO have shell access to your website go ahead and login using a shell program like Putty (our favorite). If you are on a VPS or Reseller server, you will likely have access using the <root> user which IS preferred. For shared servers, you will likely NOT have shell access and will instead have to send a support email.
NOTE: The instructions below are only for Reseller, VPS, and Dedicated server environments. The reason being is that we are granting access to a SERVICE running globally on these machine types. This is NOT something you’d want to do in a SHARED hosting environment because obviously it would open you up to a whole new set of security concerns.
However to get around this, shared hosting environments implement a technique called “suexec” which abstracts the account access yet gives proper rights to enable functionality to work as it should. SUEXEC is a topic for another blog post discussion, but you might want to mention it in your support email (should you go that route). As a matter of fact, here’s a pretty hearty discussion on the topic which you might enjoy.
Once logged in as root, execute this command:
ps aux | egrep ‘(apache|httpd)’
This should return output (and a list) like the following:
root 5597 0.0 0.1 70904 6552 ? Ss Nov18 2:03 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8715 0.0 0.0 69728 2516 ? S 17:11 0:00 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8717 0.0 0.0 70904 2608 ? S 17:11 0:00 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8718 0.1 0.4 1332864 17180 ? Sl 17:11 0:06 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8719 0.1 0.4 1333004 17012 ? Sl 17:11 0:07 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8720 0.1 0.4 1333356 16828 ? Sl 17:11 0:07 /usr/local/apache/bin/httpd -k start -DSSL
nobody 8808 0.1 0.4 1333584 16088 ? Sl 17:12 0:06 /usr/local/apache/bin/httpd -k start -DSSL
nobody 11467 0.1 0.2 1332816 11696 ? Sl 18:51 0:00 /usr/local/apache/bin/httpd -k start -DSSL
root 11611 0.0 0.0 4052 188 pts/0 D+ 18:56 0:00 egrep (apache|httpd)
The account name of nobody (highlighted in black above) indicates that THIS is my apache service account and the one I should grant access to my entire WordPress files in order for life to be good once again.
STEP 2: Grant this user rights to the WordPress install – This process is quite simple… just execute the following command within your shell windows:
chown -R nobody /home/<username>/public_html
This of course assumes that the root of your WordPress installation is within the public_html folder (quite standard on most all CPanel / Linux installations). What this command does is it starts at the root path of WordPress and grants the user called nobody with ownership rights on ALL files and folders RECURSIVELY (meaning it includes sub-folders and files within sub-folders as well) throughout the site.
So that should do it! Now go back to your WordPress admin control panel and attempt your image upload to the media library once again. You should find that all works without issue (as in the image below). Also, you will now be able to automatically update and upgrade plugins within the site.