I like using WordPress because of the ability to quickly implement many functionalities using plugins. However, to feel more confident with the magic it offers I needed an additional level of security – a backup independent of the current hosting I’m using.

So I used Github Actions experimentally to back up the files and database periodically. This allows me to keep a history of changes to both the files and the database in a private repository. The repository is updated periodically at intervals I set.

The working, experimental Github workflow is as follows:

name: Get backup
on:
  push:
    branches:
      - master
  schedule:
    - cron: '0 4 * * 0,5'

jobs:
  backup:
    name: Backup
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@master
      - name: Libs and config
        run: |
          sudo apt-get install -y lftp
          sudo apt-get install git-ftp
          git config --local user.email "mymail@xyz.com"
          git config --local user.name "GitHub Action"
      - name: Download and commit database
        working-directory: ./database
        run: |
          export MYSQL_PWD=${{ secrets.MYSQL_PASSWORD }}
          mysqldump --column-statistics=0 -h ${{ secrets.MYSQL_HOST }} -u ${{ secrets.MYSQL_USER }} ${{ secrets.MYSQL_DBNAME }} > db.sql
          git add .
          git diff-index --quiet HEAD || git commit -a -m "Database dump $(date +"%D %T")"
      - name: Download and commit website
        run: |
          git config git-ftp.url ${{ secrets.FTP_URL }}
          git config git-ftp.user ${{ secrets.FTP_USER }}
          git config git-ftp.password ${{ secrets.FTP_PASSWORD }}
          git config git-ftp.insecure 1
          git ftp download --changed-only --no-commit
          git add .
          git diff-index --quiet HEAD || git commit -a -m "Website dump $(date +"%D %T")"
      - name: Push changes
        uses: ad-m/github-push-action@master
        with:
          github_token: ${{ secrets.PERSONAL_ACCESS_TOKEN_GENERATE }}

Workflow is triggered:

  • each time there are changes to the master branch
  • by cron: at four a.m. on the first and fifth day of the week

Job runs on ubuntu-latest executing sequentially:

  • Checkout Repo – downloading files from the master branch to make them available to our script.
  • Libs and config – installation of lftp and git-ftp libraries, git configuration.
  • Download and commit database – dump the database and save it to a file using the mysqldump command, if the new copy is different from the previous one, then committing the changes.
  • Download and commit website – download the site files from the ftp server using git-ftp, if there is a difference between the previous copy and the previous one then commit the changes.
  • Push changes – publishing changes in the master branch.

The solution was implemented on short notice, certainly not the most optimal solution or the best possible one. However, it did manage to save my skin when WordPress experienced a “Technical Issue” after updating one of its plugins.

Next steps worth taking:

  • polishing the script
  • publishing the solution as Action in the Github Marketplace
  • developing a solution to restore a copy located in the repository with a single command.