I am using nginx on a multisite install.

I am trying to get WordPress to save uploads to a folder beyond the webroot :


as opposed to


I have successfully moved the uploads directory around inside the webroot with the following filter:

add_filter('upload_dir', 'my_upload_dir');
$upload = wp_upload_dir();
//remove_filter('upload_dir', 'my_upload_dir');

function my_upload_dir($upload) {
    global $blog_id;
    $upload['basedir'] = '/home/mydomain/file_secure/'.$blog_id;
    $upload['subdir'] = '';
    $upload['path'] = $upload['basedir'] . $upload['subdir'];
    $upload['url']  = $upload['baseurl'] . $upload['subdir'] . '/file_secure.php?file=';

    return $upload;

This path is writable. It even creates the directories file_secure and 25 ($blog_id)

$upload['basedir'] = '/home/mydomain/file_secure/'.$blog_id;

I have looked through the core code in WordPress 3.9 wordpress/wp-includes/functions.php at the function wp_upload_dir() and noticed that the function description states that

* Checks the 'upload_path' option, which should be from the web root folder,
 * and if it isn't empty it will be used.

I assumed that when it found my path to be outside the webroot that it should have thrown an error, but I can't find where.

Needless to say, the upload did not make it to the wanted directory.

On a side note, I plan to access the uploaded files from a script in the front end that will serve up the content. file_secure.php

Any help / direction here would be much appreciated. I would really hate to find out that I need to hack the WP core in order to make this possible; but maybe it could become available in a future release.

I would much rather all of the wp-content be located outside of the webroot.

UPDATE: all I seem to be able to do when changing the upload path from the upload_dir filter is create the folder where I want the file to go; but it does not actually save the file there. It reverts back to the default settings.

ANOTHER UPDATE: WordPress seems to think that the file exists because it creates an attachment post, but there is no file in the intended directory and the URL on the attachment simply has the default URL structure and not the one that I set above.

So now I am trying to investigate what is going on during the attachment post creation. If anyone can spot what I may be doing wrong, please let me know.

  • Are you trying to move ALL uploads or certain uploads directory? There's a constraint you can define in wp-config that apprently sets the uploads folder: View Codex – Howdy_McGee Apr 21 '14 at 20:51
  • all uploads would be fine, but the 'upload_dir' filter should replace the uploads folder set in the wp-config file – Douglas.Sesar Apr 21 '14 at 21:04
  • Your server/OS may prevent uploads outside of the web root. There are server and filesystem level configuration issues to worry about when you do this. – s_ha_dum Apr 21 '14 at 21:12
  • I checked those specifics and I have write access beyond the webroot with my nginx php script user. As noted above, I can now create the directory with my code, but the actual file does not get saved there. – Douglas.Sesar May 7 '14 at 20:57
  • It did turn out to be permissions related, but I ended up not using Wordpress to upload the files anyway. – Douglas.Sesar Jun 14 '14 at 1:02