Backing Up Trellis Sites to an S3 Bucket

Add backup shell script

Create site/scripts/ with the following contents:

eval $(cat ../.env | sed 's/^/export /')
export AWS_CONFIG_FILE="/home/web/.aws/config"
TIMESTAMP=`env TZ=America/Denver date +%Y-%m-%d-%H%M`
mkdir -p $ARCHIVE_PATH &&
cd /srv/www/$SITE/current && wp db export $ARCHIVE_PATH/db.sql &&
rsync -kavzP --exclude web/wp/ --exclude web/wp-config.php /srv/www/$SITE/current/web $ARCHIVE_PATH &&
rsync -kavzP /srv/www/$SITE/shared/uploads $ARCHIVE_PATH/web/app &&
/usr/local/bin/aws s3 cp /tmp/$ARCHIVE_FILENAME s3://site-backups/$SITE/$ARCHIVE_FILENAME &&
rm -rf $ARCHIVE_PATH &&


  • Replace s3://site-backups with the name of an existing S3 bucket
  • Make sure the permissions for site/scripts/ allow it to be executed (chmod +x

Trellis modifications

Add to wordpress-setup/tasks/main.yml:

- name: Setup nightly cron for S3 backup
    name: "{{ item.key }} nightly S3 backup"
    minute: "0"
    hour: "12"
    user: "{{ web_user }}"
    job: "cd {{ www_root }}/{{ item.key }}/{{ item.value.current_path | default('current') }}/scripts && ./ > /dev/null 2>&1"
    cron_file: "backup-nightly-{{ item.key | replace('.', '_') }}"
  with_dict: "{{ wordpress_sites }}"
  when: env != 'development'

Add to trellis/galaxy.yml:

- name: aws-cli
  version: 5c1c14d9b0e6264605bd475c86d4ea67e7d5896f

And then run ansible-galaxy install -r galaxy.yml.

Add to trellis/server.yml:

    - { role: aws-cli, tags: [aws-cli] }

Add to trellis/group_vars/all/vault.yml:

vault_aws_access_key_id: xxxxxxx
vault_aws_secret_access_key: "xxxxxxx"

Join the discussion on Roots Discourse

Help support our open-source development efforts

Help us grow

Join over 7,800+ subscribers on our newsletter to get the latest Roots updates, along with occasional tips on building better WordPress sites.

Looking for WordPress plugin recommendations, the newest modern WordPress projects, and general web development tips and articles?

“Easily the best WordPress email I get.” Colin OBrien

Follow us on Twitter @rootswp

Ready to checkout?