Using Extensions That Assume Write Access

Learn how to create symbolic links from the code directory to a file.

Some modules and plugins create files within hard-coded paths outside of the standard path for the given framework, which can be problematic on Pantheon. WordPress stores files within wp-content/uploads and Drupal uses /sites/default/files. These directories are symbolically linked to Pantheon's cloud-based filesystem, Valhalla, which is writeable on all environments. Extensions that create files within the codebase (e.g. wp-content/plugins/plugin-name/some-other-directory or /sites/all/modules/module-name/some-other-directory) incorrectly assume write access that is not granted on the Live and Test environments.

The best solution is to communicate with the maintainer of the module or plugin and request that hard-coded, nonstandard paths be fixed. Alternatively, you can create a symbolic link as a workaround to avoid failures on Test and Live.

  1. On your Dev environment's Dashboard, change the Connection Mode from SFTP to Git mode. Install Git and clone the code locally if you have not done so already.


    We do not recommend creating symlinks over SFTP due to inconsistencies amongst clients.

    The following is for Mac and Linux only. Windows users may refer to Microsoft documentation for opening Command Prompt as an Administrator and creating symlinks using mklink or create symlinks within a virtual machine.

  2. From your terminal, cd to the site code repository:

    cd ~/sites/myawesomesite/ #Change this to your project directory.
  3. Move the directory you want to replace with a symlink. This serves two purposes; backing up any data that may otherwise be lost, and preventing the symlink from being nested inside the existing directory:

    mv ./wp-content/path/plugin-expects-write-to ~/backups/

    The command above moves the directory to a folder named backups in your home directory. ~/. Replace this with an existing backup location.

  4. Create a symlink for the standard files path:

    # The first path will be used as the new file destination instead of whatever path the plugin assumed write access to
    ln -s ./wp-content/uploads/new-directory ./wp-content/path/plugin-expects-to-write-to


    The ln command is sensitive to the working directory, the folder your prompt is currently sitting in. The example above assumes you're in the main directory of your local git repository.

  5. Stage your changes

    git add .
  6. Run git status to review your current index, then commit your changes:

    git commit -m "symlink non-standard files path to wp-content/uploads"
  7. Push the changes to Pantheon:

    git push origin master

    Your commit can be seen in the Dev environments commit history. The plugin will now successfully write files within any environment, even when the Dev environment's connection mode is set to Git. In your previous configuration, the plugin would fail while in Git mode. You should not see the newly created files in the Dashboard as "ready to commit", as files are not version controlled.


    In our example, we created the target directory of the symlink as ./wp-content/uploads/new-directory. Make sure this directory is created via SFTP if it does not exist yet.

  8. Deploy to Test and confirm results.

  9. Deploy to Live and perform the plugin operation that creates the desired files, then confirm results.


As discussed in Modules and Plugins with Known Issues, WP-Rocket assumes write access to the code base.

For MacOS & Linux:

From the wp-content directory:

ln -s ./uploads/cache ./wp-content/cache
ln -s ./uploads/wp-rocket-config ./wp-content/wp-rocket-config

To verify, use ls -al:

cache -> ./uploads/cache
wp-rocket-config -> ./uploads/wp-rocket-config

For Windows:

Note that the syntax for Windows is opposite from MacOS and Linux, requiring the symlink path before the target:

mklink /d ./wp-content/cache ./uploads/cache
mklink /d ./wp-content/wp-rocket-config ./uploads/wp-rocket-config

Each command will return the following upon success:

symbolic link created for .\wp-content\cache <<===>> .\uploads\cache
symbolic link created for .\wp-content\wp-rocket-config <<===>> .\uploads\wp-rocket-config

To verify that you have done it correctly, you should have these when you list your folders in wp-content directory: You can also verify success using dir:

<SYMLINKD>        cache [.\uploads\cache]
<SYMLINKD>        wp-rocket-config [.\uploads\wp-rocket-config]


If a site no longer needs a symlink, because you uninstalled the plugin that required it for example, you can simply remove the symlink file from your codebase using rm. Move back any folders from the public files folder that should be tracked by version control.

Modules That Verify Directories

Some modules and plugins verify that the target directory exists using is_dir() which returns bool(false) if the directory is a symlink. It may help to patch the module/plugin to use is_link() instead of is_dir().

If a symlinked folder doesn't show the proper contents, doublecheck that the path is correct. In Bash, ls -l will show symlinks paths:

$ ls -l

lrwxr-xr-x  1 user  group     39 Sep 13 14:29 images -> ../plugins/some-plugin/images/

Try changing the working directory in which you create the symlink, using ../ to refer to directories above the working directory, and ./ to refer to the currect directory.

See Also

For more details on creating symbolic links on Mac/Linux, see this thread.