When you work with a Trellis WordPress LEMP setup to manage a client site migration is set up pretty well. You can use scripts for server provisioning and site deployment. However, there are certain things that will / should not be in your git repository. These items will not be synched. Media in the uploads folder is one of them. Let me explain the reasons behind this and how Trellis media migration can be achieved.

Bedrock Ignores Uploads

Certain files and or directories are ignored by default using a .gitignore in Bedrock. This is because they will not stay the same locally and and live. They are often too big to be kept there or they are managed and installed by composer. The complete ignore list for Bedrock is:


# Application

# WordPress


# Dotenv

# Vendor (e.g. Composer)

# Node Package Manager

# Vagrant

One of the elements that are not in the repository and ignored using a .gitignore file are all the images and other media in the uploads folder. This is because they often take up too much space in a repo. And as said because often content on local server and remote server are not the same.

Synchronizing Media

Sometimes you do want to synch local media with the staging or remote server though. You may have set up a site with basic pages and posts including images and other files locally. In that case you do not just want to migrate the files and start from scratch. You then want to move the files, database and all media. To move all media files there are two things you can do. You can either sftp all files to the server as admin or use an Ansible Playbook to synchronise them.

SFTP Uploads

You can use SFTP and SCP to upload all to the server. Then you use SSH to move it to the right location and change the rights and permissions. Swalkinshaw suggested the following here:

As you can see these steps require an (S)FTP program like Filezilla to upload all and the terminal to move things around and change permissions. For most Trellis users not an issue really.

Ansible Playbook to Synch Media

CFX in the same Roots Discourse thread mentioned a playbook that is available at Github Gist. The script was made by Louis-Michel Couture. With it you can synchronize your uploads content by just running the script with the following simple command:

ansible-playbook uploads.yml -i hosts/staging --extra-vars="site=example.com mode=push"

You do need to make sure the uploads.yml is in your site’s web root. And you of course need to change the domain. Push is for going from local server to staging or production.

Here is the whole script as in the gist:

- name: Sync uploads between environments
  hosts: web
  remote_user: "{{ web_user }}"

    project: "{{ wordpress_sites[site] }}"
    project_root: "{{ www_root }}/{{ site }}"

  # ansible-playbook uploads.yml -i hosts/staging --extra-vars="site=example.com mode=push"
  - name: Push uploads
      src: "{{ project.local_path }}/web/app/uploads/"
      dest: "{{ project_root }}/current/web/app/uploads/"
      rsync_opts: --exclude=.DS_Store
    when: mode is not defined or mode == "push"

  # ansible-playbook uploads.yml -i hosts/staging --extra-vars="site=example.com mode=pull"
  - name: Pull uploads
      src: "{{ project_root }}/current/web/app/uploads/"
      dest: "{{ project.local_path }}/web/app/uploads/"
      mode: pull
      rsync_opts: --exclude=.DS_Store
    when: mode is defined and mode == "pull"

I did use it and it works well. You just do not see progress and it can take some time for all the files to have been uploaded.

My favorite

In the end I think I would pick sftp. It does show you progress and there is the option to gzip or zip all before upload. This will be quicker. You will then have to ssh into the server, but if you are good at it this will be quicker. the Ansible Playbook is the lazier or easier option, but it will take more time.

Leave a Reply

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