Nuova sezione libri disponibile!

Database Backup on GitHub using GitHub Action

Ludovico Russo

lettura in 3 minuti

When hosting a server, database backup is an important procedure to run periodically properly reponde to incident or data loss. Usually, database backup are performed on the same machine where the database is hosted using cronjob or scheduled task and backups are stored on cloud providers like AWS S3, Google Cloud Storage, etc, where cost is really small (some cents per month).

However, for small applications, like a blog, there is a simpler and cheaper solution (pratically free), that is storing database backup direcly on a private github repo.

This procedure is even more simple thanks to github actions that allows to run an action periodically.

In this post, I show you how to leverage a scheduled GitHub actions to periodically backup a small database on a github repo.

Limitaiton

This solutions works with small databases that does not change very often. In my case this is done for a small blog that I've build for my wife. The blog is hosted on a kubernetes cluster with a dedicated database (I know, it's too much but I've also created it for fun 😅) and posts are updated few times a month.

If you are curious, you can find the blog here.

This solutions does not work with big database that change often, this is because github has a limited amount of data you can store on a single repo, and in general git is not for backups but for code. But if you a have a pet project with a small database, you can use this solution.

Creating the Action

Les't start creating a new private github repo that will host the database backups and the github action definition. The action will connect to the database, perform database backup (in my case pg_dump) and commit the changes in the local reposiroty.

We need to create a file in .github/workflows/ called backup.yml that will contain the definition of the action.

We will leverage two open github actions:

Moreover, to connect to the database on kubernetes, we can leverage the github action service container to perform port forwording as described in my previous blog post.

Here is the complete action

name: Backup

on:
  schedule:
    - cron: "0 0 * * *"
  workflow_dispatch:

jobs:
  backup:
    permissions:
      contents: write
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2
      - name: Get Vars
        id: get_vars
        run: |
          echo "::set-output name=date::$(date)"
          echo "::set-output name=ts::$(date +%s)"
      - run: sleep 2
      - name: Postgres Dump Backup
        uses: tj-actions/pg-dump@v2.3
        with:
          database_url: ${{ secrets.DATABASE_URL }}
          path: "backups/backup.sql"
          options: "-O"
      - uses: EndBug/add-and-commit@v9 # You can change this to use a specific version.
        with:
          add: "backups"
          author_name: <your name>
          author_email: <your email>
          commit: --allow-empty
          default_author: github_actions
          message: "Backup ${{ steps.get_vars.outputs.date }}"
          tag: "bk-${{steps.get_vars.outputs.ts}}"
    services:
      db:
        image: ghcr.io/ludusrusso/kubectl-with-env-config:958062ab64ccfa815aa2f931c03f72a2a670232a
        env:
          KUBECONFIG: "${{ secrets.KUBE_CONFIG }}"
          NAMESPACE: "${{ secrets.NAMESPACE }}"
          POD: "${{ secrets.POD }}"
          PORTS: 5432:5432
        ports:
          - 5432:5432

Before pushing to the reposiroty, we also need to create a file backups/.gitkeep in order to create the folder backups where the backup will be stored.

Using the actions

Once committed and pushed, the action will automatically run every day at midnight. Backups will be stored in the backups/bakckps.sql file in the github repo. And each backup will be tagged with timestamp of the backup itself.

commits tags

You can also run the action manually on the "action" tab on github.

run

Ti è piaciuto questo post?

Registrati alla newsletter per rimanere sempre aggiornato!

Ci tengo alla tua privacy. Leggi di più sulla mia Privacy Policy.