Trellis-Backup, an ansible role for local backups

Continuing the discussion from Your Agency's Backup Plan:

I’ve created a preliminary GitHub repo of an Ansible role for defining a set of backup jobs called Trellis-Backup.

The goal is to use the existing site information defined by Trellis to configure useful backup jobs, which are in turn created by Stouts.backup, that will be stored locally on the server. These can then be moved/rsynced/included in snapshots for a more thorough backup solution.

Currently two jobs are defined per site in group_vars/production/wordpress_sites.yml:

  • Uploads
  • Database

I would love some feedback on this. I am brand new to Ansible and have honestly muddled my way through this as best I can. If anyone with a better handle on Ansible and best practices could take a look I would really appreciate it.

One final note, I briefly investigated using ansible-duply-backup, but it appears with the way they define their backup job keys, I cannot automatically create jobs using {{ wordpress_sites }} the way I can with Stouts.backup. If anyone has a way to do this, so that I can use that more mature project instead to create the backup jobs, that would be great.

Thank you for your time!


There appears to be a problem with Stouts.backup that’s preventing jobs from running (a hard coded path to Duplicity is incorrect). I’ve submitted an Issue on their GitHub here.

Here’s a rundown of the fix:

In Stouts.backup/templates/cron.j2


{{profile.schedule}} {{profile.user|default(backup_user)}} /usr/local/bin/duply {{backup_home}}/{{}} {{profile.action|default('backup')}} >> {{backup_logdir}}/{{}}.log 2>&1


{{profile.schedule}} {{profile.user|default(backup_user)}} /usr/bin/duply {{backup_home}}/{{}} {{profile.action|default('backup')}} >> {{backup_logdir}}/{{}}.log 2>&1

Quick follow-up, Stouts.backup appears to have fixed the above problem, so trellis-backup should work out of the box now!

1 Like

@MWDelaney First of all, thanks for this! I followed your readme instructions and ran into an issue when I first tried to reprovision my server the role failed with the following error:

'mysql_root_user' is undefined

I tried adding your two roles under the existing heading:

- name: WordPress Server - Install LEMP Stack with PHP 7.0 and MariaDB MySQL

…and it worked. I’m not sure if this warrants an update to your readme. In any case, thanks so much for your work.

1 Like

Hi @MWDelaney !

I inspired from your work to install remote backup in production in my organization, and it works perfectly.

Also I made a PR from the work I had done in my company from the work you had done :

This is more a call for comments than a finished proposition.


Wow, I am extremely flattered. I’m going to try out your code on one of my development sites as soon as I can!

If it turns out that Roots doesn’t want to include this feature in Trellis (I could see that going both ways), I would be happy to merge your changes into Trellis-Backup and continue to maintain a separate repo, so feel free to send a PR my way, too!

Thanks again for your kind words!

1 Like

Hello @guilro!

I’m experimenting with trellis-backup-role. The states that I should setup my roles as:

    ... other Trellis roles ...
    - { role: backup, tags: [backup] }
    - { role: Stouts.backup, tags: [backup] }

When I do this, I get an error when provisioning: ansible-playbook server.yml -e env=staging:

ERROR! the role 'backup' was not found in <path-to-app>:<path-to-role>:<path-to-trellis-root>

The error appears to have been in '<path-to-trellis-root>/server.yml': line 50, column 7, but may be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

# Ref:
- { role: backup, tags: [backup] }
  ^ here

When I comment out #- { role: backup, tags: [backup] } the provisioning step works.

Do I need the line - { role: backup, tags: [backup] }?

Thanks in advance for your feedback.

Hello @silumesii.

This is all my fault, I forgot to change the name of the role after setting it up as a Galaxy role. The name of the role in Ansible Galaxy is trellis-backup, so should be the name in the playbook.

I edited the README according to this change.

Thanks !

1 Like

Hello @guilro,

I am experimenting with trellis-backup in a development environment and get this error during installation:

Would it help to create an issue on GitHub?

Hello, @guilro!

It looks like the issue is with python-openssl.

When provisioning fails (gist above) and I vagrant ssh into my development server, running pip --version produces the following:

$ pip --version
Traceback (most recent call last):
  File "/usr/bin/pip", line 9, in <module>
    from pip import main
  File "/usr/lib/python2.7/dist-packages/pip/", line 13, in <module>
    from pip.exceptions import InstallationError, CommandError, PipError
  File "/usr/lib/python2.7/dist-packages/pip/", line 6, in <module>
    from pip._vendor.six import iteritems
  File "/usr/lib/python2.7/dist-packages/pip/_vendor/", line 64, in <module>
  File "/usr/lib/python2.7/dist-packages/pip/_vendor/", line 36, in vendored
    __import__(modulename, globals(), locals(), level=0)
  File "/usr/share/python-wheels/CacheControl-0.11.5-py2.py3-none-any.whl/cachecontrol/", line 9, in <module>
  File "/usr/share/python-wheels/CacheControl-0.11.5-py2.py3-none-any.whl/cachecontrol/", line 1, in <module>
  File "/usr/share/python-wheels/CacheControl-0.11.5-py2.py3-none-any.whl/cachecontrol/", line 3, in <module>
  File "/usr/share/python-wheels/requests-2.9.1-py2.py3-none-any.whl/requests/", line 53, in <module>
  File "/usr/share/python-wheels/urllib3-1.13.1-py2.py3-none-any.whl/urllib3/contrib/", line 54, in <module>
  File "/usr/lib/python2.7/dist-packages/OpenSSL/", line 8, in <module>
    from OpenSSL import rand, crypto, SSL
  File "/usr/lib/python2.7/dist-packages/OpenSSL/", line 118, in <module>
AttributeError: 'module' object has no attribute 'SSL_ST_INIT'

Reinstalling python-openssl fixes the problem:

sudo apt-get remove --purge python-openssl
sudo apt-get install python-openssl

This gives expected output:

$ pip --version
pip 8.1.1 from /usr/lib/python2.7/dist-packages (python 2.7)

After this, reprovisioning works.

Now to get Trellis to install a working python-openssl out of the box :slightly_smiling_face:

1 Like

…Huh, I experienced the same issue with python-openssl, too, except when I wiped the py-openssl directory, pip croaked and died to the point where I’m going to blow the machine away and start again.

I really want it working on a dev server. Being able to build locally and then just import remotely is a pretty big win for me.

1 Like

I’m having success pre-installing python-openssl by adding it to trellis/roles/common/defaults/main.yml

    - python-openssl # For trellis-backup-role to work

Hope this helps you.

I’m currently having a challenge setting up the usernames and passwords for the backups. The is unclear on how to define those.

1 Like

That does help – thanks!!

As to your issue, I left a comment in the Github thread but I’ll reprise it here:

Yeah, it’s not super well documented yet, but you need to set up some backup information within wordpress_sites.yml or vault.yml. The above error is basically just saying you don’t have a backup_target_user key.

What you need is something like this in your vault:

  <site domain>:
      db_password: #...
      # ...
      backup_target_user: ""
      backup_target_pass: ""

If you’re using S3, you need to specify your access key as the user and secret as the pass.

I’ll try to do a PR with these documentation details soon.

1 Like

Thank you, @robyurkowski!

Your recommendations work for me in development. In production, I’d like to use S3. If you have configuration notes on how to set that up, I’d appreciate those.

Thanks in advance.

Happy to share. It’s pretty simple unless you’re using a non-US bucket. In the case that your bucket only has V4 Signatures, you’ll have to use the code in my fork until the pull request is accepted.

If you do need the V4, the code you’d want looks something like this (and please forgive me because I’m doing this from memory — I may mis-key something.)

# group_vars/production/wordpress_sites.yml

  <site domain>:
      # ...
      target: "s3://<region-identifier><bucket>/<subfolder>"
        - 'export S3_USE_SIGV4="True"'

If you have a bucket that accepts V2 signatures, you don’t need the params field.

# group_vars/production/vault.yml

  <site domain>:
      # ...
      backup_target_user: "<AWS ACCESS KEY>"
      backup_target_pass: "<AWS SECRET KEY>"

There are a couple extra things I noted:

  1. Make sure your bucket doesn’t have a period in it. Duplicity doesn’t like that.
  2. I had issues when I used as my region identifier, but not s3-ca-central-1. However, I was also debugging the S3_USE_SIGV4 issue at that time, so that might not be important.
  3. Make sure you have a bucket policy that allows basically everything inside of the bucket.

As a side note, I’m still having issues with the backups. I checked the logs last night (/var/log/duply/) and it turns out that it’s not connecting to MySQL and the purge operation isn’t working. So more debugging needed. (EDIT: Looks like there’s a PR to fix that too.)

PS: @guilro, if you’ve got some time, we could use some PRs reviewed and merged! Otherwise I’m sure one of us would be happy to hop on as a maintainer!


Hi everyone, thanks for your PRs, most of them have been merged.

I normally have time to maintain the role (we use it in production at my company), I was just spending a week off with my family.

I will check the python-openssl problem, it should be sufficient to add the package in the role.

1 Like

It should have been fixed in version 1.1.0, at least on the Ubuntu image my provider is working with.

If you still meet problems, can you tell me the providers you are using so I can reproduce ?

1 Like

Thank you, @guilro and @robyurkowski. The latest updates work as advertised for me from the docs in the new to the S3 backups. Thanks!

Thanks, @guilro! Hope you had a great week off. :slight_smile:

I’ll verify that everything is working tonight.

I would like to see the ability to redirect this backup to the same Git repo that the site is located at, but in a separate branch.