One Line GitHub Backup Automation

Motivation

I wanted a quick, no BS automated daily backup of my configuration files on GitHub. Things I needed:

  • No password! -> Must use certificate.
  • No feedback -> Pipe feedback to null.
  • Simple automation -> Single line in cron.

N.B. there is a lot of text, but only to be very descriptive. It’s a very quick process!

Quick Summary

  1. Create repo
  2. Create key
  3. Upload Deploy Key
  4. Change git remote
  5. Set cron task

Setup Config Directory witth Git

You can follows steps 1-5 inclusive of this HA GitHub guide to get your configuration directory setup, and to make sure you can successfully push to GitHub.

Create Single Key

in the terminal under the user that is the owner ( homeassistant in my case) for the HA configuration files. Create the key for the `homeassistant` user by doing the following.
homeassistant@hassbian:~/.homeassistant $ ssh-keygen
Generating public/private rsa key pair.
# Leave the default location for the user, which is inside the .ssh folder in the home dir of the user.
Enter file in which to save the key (/home/homeassistant/.ssh/id_rsa):
# Press enter twice to not assign a password to key. 
Enter passphrase (empty for no passphrase):
The keys randomart image is:
+---[RSA 2048]----+
|       ....      |
|. .   ...o .     |
|.o o   ++ o      |
|. o * Booo       |
|   * &.=S .      |
|    %.=. .       |
| . *.Xo o        |
|. *.+ E+         |
|o. ..o.          |
+----[SHA256]-----+
# Certificate is complete!
homeassistant@hassbian:~/.homeassistant $

Upload Deploy Key

  1. Go to your GitHub repo online
  2. Click Settings in the top bar
  3. Click Deploy Keys
  4. Click Add deploy keys (in the top right)
  5. Give is a meaning Title for later
  6. Back in the terminal, use the following command to print out your public key: cat ~/.ssh/id_rsa.pub
  7. Copy the entire text, from ssh-rsa to homeassistant@hassbian inclusive.
  8. Paste into the the Key field!
  9. Tick Allow write access so your HA can push code

Change Git to an SSH Remote

If you followed the guide, you will need to change from password based authentication with HTTPS to key authentication with SSH. Instruction pulled from Git [here](https://help.github.com/articles/changing-a-remote-s-url/)
  1. Back in your repo on github.com, click on the green “Clone” button
  2. Choose SSH
  3. Cop contents
  4. Paste the following into terminal:
git remote set-url origin [PASTE]
# Should look similar to this "git remote set-url origin [email protected]:USERNAME/REPOSITORY.git"
  1. as a test, run a git pull and it shouldn’t ask you for a password!

Automate with Cron

  1. Back in terminal (still as the same user) type crontab -e
  2. Choose the /bin/nano option, which is 2 for me. as is below:
homeassistant@hassbian:~ $ crontab -e
no crontab for homeassistant - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.basic
  4. /usr/bin/vim.tiny

Choose 1-4 [2]: 2
  1. Paste the following on the last line of the opened file:
0 2 * * * /bin/bash -c "cd /home/homeassistant/.homeassistant && git commit -am 'Daily commit `date`' --quiet &> /dev/null && git push --quiet"
  1. Save and exit with Ctrl+x, and press Y then enter.
  2. Confirm the command is saved with crontab -l (lowercase “L”)

Explanation of the Cron Automation

What this will do is, everyday at 2AM, add all changed files to the Git "commit" and call it "Daily commit" then the date and time e.g.
Daily commit Sun 4 Feb 02:00:01 AEDT 2018

Suppress all messages, and push put to GitHub!

Debugging and/or Changes

  • If you need to change the date, time, or frequency, best thing to do is Google what you wish to make it. E.g. “cron every 30 minutes”
  • If you feel like the cron is not working, paste the following part of the command into the terminal as the user who will push the code:
/bin/bash -c "cd /home/homeassistant/.homeassistant && git commit -am 'Daily commit `date`' && git push"
# This will print out messages which might hint to what is wrong in Git.
10 Likes

Thanks a lot for this tutorial. It’s a good add on the existing GitHub tutorial and exactly what I was looking for!

1 Like

Nice idea automating the commits.

I’m using hassio so setting up cron may be a bit of a pain - could I use command line switch instead: https://www.home-assistant.io/components/switch.command_line/ then just set up an automation to trigger daily?

Should be able to. Place the one liner in there and off you go!

1 Like

One must note, that the provided one line git command is quite dangerous in the meaning of backup. Let me explain, what i mean:

git commit -am

From GIT docs:
-a
–all
Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.

-m
–message=
Use the given as the commit message…

What this mean basically - **git commit -a** never adds untracked files. It adds modified files and deleted files. So after the first initial commit to GitHub with

git add .

git commit
.....

Any new file you add to your config dir will stay unstaged, until you run git add . again, thus relying only on the above command to have full config backed up is very dangerous and you my get up with only partial backup.

I believe the proper command should be:

/bin/bash -c "cd /home/homeassistant/.homeassistant && git add --all && git commit -m 'Daily commit `date`' && git push"`
1 Like

Thanks for your input.

None of what you said makes this command “dangerous” in any sense.
At most, it makes it an incomplete solution .

For the record, it was my direct intent to avoid arbitrarily tracking all files.
Your solution would include database files and temporary files, such as VIM .swp files.

I would rather manually include files to prevent such a case.

As I said it - is dangerous in the meaning of backup, real full backup. Ok my apologies maybe dangerous is a bit of overstatement, but for some users that want to “set it and forget it” forgetting to

git add .

after adding files dirs etc. can cause headaches in case they rely on that they already configured cronjob to synchronize their config and don’t bother to check.

You are also right about including of temp files but my logic is that .gitignore should always starts with * ensures that everything will be ignored and then whitelisting what files/folders shouldn’t.

Otherwise your example is very good and very usefull

great write up thanks!

Just to follow up on a previous post, any possible way to get an automation to run in Hass.io to perform a git push? looks like

thank you for this guide, it’s exactly what I was looking for!

1 Like

It turns out it is a bit more complicated to get it to trigger inside HASS:
Steps I had to go through to make this work:

  1. In VSCode inside home assistant: open a terminal
  2. Type the following commands:
cd ~/config
mkdir githubconf
mkdir commandline_logs
cp ~/.ssh/id_rsa githubconf/id_rsa
cp ~/.ssh/id_rsa githubconf/id_rsa.pub
chmod 400 githubconf
chmod 400 githubconf/id_rsa
chmod 400 githubconf/id_rsa.pub
git config --add --local core.sshCommand 'ssh -i githubconf/id_rsa -o StrictHostKeyChecking=no'
  1. Create the following switch in configuration.yaml
switch:
  - platform: command_line
    switches:
      github_configuration_commit:
        unique_id: github_configuration_commit_switch
        command_on: "git commit -am 'Daily commit `date`' && git push"
      # Extra switches for testing purposes
      github_commit_test:
        unique_id: github_commit_test
        command_on: "git commit -am 'Daily commit `date`' &> commandline_logs/commit.log"
      github_push_test:
        unique_id: github_push_test
        command_on: "git push &> commandline_logs/push.log"

With the last two switches, you can troubleshoot by looking at the generate log files in case it is not working.

  1. Create an automation that turns on github_configuration_commit