Aug 2, 2018 - Mario de la Ossa    

How to simplify your smart home configuration with GitLab CI/CD

How to use GitLab pipelines to automatically test and deploy new home-assistant configurations, wherever you are.

So you've read all about the Internet of Things and all the cool stuff you can do with it – from setting up timers for your lights to making your breakfast – and now you're itching to get started? Great!

If you're a power user, you've probably settled on using Home Assistant as your smart home hub, but this choice has a few pitfalls:

  • It's annoying to SSH into the server itself to change configuration. Wouldn't you like to use your favorite local editor instead?
  • How do you keep your configuration backed up?
  • How do you protect yourself from accidentally messing up the configuration?

In this guide we'll show you how to fix these annoyances yourself, thanks to Git and the power of GitLab Pipelines! We will set up a pipeline that will check your home-assistant configuration and deploy it to your home-assistant install, giving you the power to deploy changes from anywhere in the world with a simple git push! Did you go on vacation and forget you wanted your lights to turn on and off randomly to make it seem like someone's home? No worries! Just open GitLab's Web IDE and make your changes from your hotel room.

By the end of this tutorial you'll have:

  • Automatic configuration backups thanks to git. You'll be able to see the history of every change you've made and revert changes easily.
  • Automatic configuration testing via GitLab pipelines. Never again will a simple typo have you scratching your head, wondering why things don't work!
  • An easy way to push changes to your Home Assistant configuration without having to SSH into the server.

Requirements

In this guide we'll be assuming a few things:

  • You installed Home Assistant using the Docker image
  • The server Home Assistant runs in is accessible from the internet via SSH (or you're using a self-hosted GitLab installation in the same network)

Set up your server

  1. Navigate to your Home Assistant configuration folder.
  2. Create a new file called .gitignore with the following content:

    *.db
    *.log
    
  3. Initialize the Git repo

    git init
    git add .
    git commit -m 'Initial commit'
    
  4. Create a new GitLab project and push to it

    git remote add origin YOUR_PROJECT_HERE
    git push -u origin master
    

With this you now have a backup of your Home Assistant configuration. Let's now set up the GitLab pipeline!

Setting up the pipeline

We have a few goals for the CI/CD pipeline:

  • Test the new configuration to ensure it's valid
  • Deploy the new configuration to the Home Assistant server
  • Bonus: Notify us of a successful deployment, since the default is to only notify for failures

The complete .gitlab-ci.yml can be found here.

General documentation for how to configure jobs can be found here.

We will be using the following stages in our pipeline:

  • test: Will test the Home Assistant configuration to ensure it is valid
  • deploy: Will update the Home Assistant configuration in the server and restart Home Assistant
  • notify: Will send a push notification with success/failure state

Since these aren't default pipeline stages we need to declare them in our .gitlab-ci.yml like so:

stages:
  - test
  - deploy
  - notify

Automating configuration testing

Since GitLab CI/CD supports Docker images and Home Assistant is available as a Docker image, this is a fairly straightforward stage to add.

Add this to your .gitlab-ci.yml file:

test:
  stage: test
  image: homeassistant/amd64-homeassistant
  script:
    - hass --script check_config -c .

With this we are creating a job called test which will run in the test stage. We're using the homeassistant/amd64-homeassistant image because it exposes the hass command globally so we can use the built-in configuration checking command on our committed files. That's it!

Feel free to commit and push this change to test it out!

git add .
git commit -m 'Added testing stage to GitLab pipeline'
git push

You'll now see that a pipeline gets created whenever you push:

HASS Test pipeline success

If your configuration contains any errors, they'll be shown in the Failed Jobs view of the pipeline and you'll get an email notifying you of the failure:

HASS Test pipeline failure

Automating deployments

Now that we have automated testing, let's add another stage that will deploy our new configuration if the tests pass!

"Deploying" in this case will consist of:

  • SSHing into the server
  • Doing a git pull to pull down changes from the repo
  • Restart the Home Assistant Docker image

Preparing the server (and GitLab) for SSH access

Since we will be using SSH we need to prepare our server first. We'll follow these instructions from the GitLab documentation. We will also set some CI/CD Variables.

  1. Generate a new SSH key pair. It's OK to save them to the current folder as you'll delete them later anyway.

    ssh-keygen -t rsa -C "hass-deploy" -b 4096
    
  2. On the server that runs Home Assistant, save the contents of the public key (the file ending in .pub) to /home/user_running_hass/.ssh/authorized_keys
  3. Go to your GitLab project's CI/CD variables (inside Settings). Add the contents of the private key file to a variable named SSH_PRIVATE_KEY. You can now delete the SSH key pair files if you'd like, or store them somewhere safe.

We also need to add our server's host keys to the GitLab runner so the runner will be able to SSH successfully. Alternatively we could disable host key checking, but this is not recommended.

  1. On your server, run ssh-keyscan example.com where example.com is the domain or IP of your server.
  2. Create a new CI/CD variable called SSH_KNOWN_HOSTS and add the output of ssh-keyscan to it.

You should also create two other CI/CD variables (optional):

  • DEPLOY_USER: the user running HASS that the runner with SSH into the server as to perform the deploy
  • DEPLOY_HOST: the domain or IP of the server

The deploy stage

Now that we have prepared our server and GitLab CI/CD variables, we can add our deploy stage to .gitlab-ci.yml. Please note that we are using the only: keyword so that only new commits in the master branch will attempt a deploy.

deploy:
  stage: deploy
  only:
    - master
  before_script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - ssh $DEPLOY_USER@$DEPLOY_HOST "cd '$DEPLOY_PATH'; git pull; docker restart home-assistant"

The before_script above is in charge of:

  • Making sure ssh-agent is installed and installing it otherwise
  • Making sure ssh-agent is running
  • Adding the SSH_PRIVATE_KEY to the keys to use when logging into a server
  • Creating the .ssh folder with required permissions
  • Adding the values we added to the SSH_KNOWN_HOSTS variable to the proper location

The script portion is what actually deploys our new configuration:

  • We cd into the proper location (where the Home Assistant configuration files are kept)
  • We update the configuration with a git pull, since this directory is a Git repo
  • We restart Home Assistant (in this case the Docker image was created with the name home-assistant. Please use the name of your container)

Note: If you did not create DEPLOY_USER and DEPLOY_HOST variables on GitLab, please replace the proper values in the script

Now let's commit and push this new stage to GitLab!

git add .
git commit -m 'Added deploy stage to GitLab pipeline'
git push

With this new stage added, you can now edit your configuration from anywhere (including the GitLab Web IDE!) and be confident that these changes will be pushed to your Home Assistant server if there are no issues with the configuration. There's no longer a need to figure out how to connect directly to your Home Assistant server to make the edits you need.

Bonus: Successful deployment notifications

You'll notice that if the configuration is wrong or an error occurs during the deployment, you will get an email notification, but what about when everything runs successfully?

We have two options:

  1. Enable the Pipeline Emails integration and set it to notify on every pipeline
  2. Add a new stage called notify and use it to send push notifications to your phone

While email is really nice, there's something really satisfying about getting push notification for your services, so let's set things up using Pushover. You'll need to create an 'Application' and add the token you get to a GitLab variable called PUSHOVER_API_TOKEN. You'll also need to add your user key to a variable called PUSHOVER_USER_TOKEN.

Since we'd like a different notification depending on whether our pipeline passed or failed, we will be adding two jobs to the notify stage:

notify_success:
  stage: notify
  allow_failure: true
  only:
    - master
  script:
    - curl -s --form-string "token=$PUSHOVER_API_TOKEN" --form-string "user=$PUSHOVER_USER_TOKEN" --form-string "message=New Hass config deployed successfully!" https://api.pushover.net/1/messages.json

notify_fail:
  stage: notify
  allow_failure: true
  only:
    - master
  when: on_failure
  script:
    - curl -s --form-string "token=$PUSHOVER_API_TOKEN" --form-string "user=$PUSHOVER_USER_TOKEN" --form-string "message=New Hass config failed. Please check for errors" https://api.pushover.net/1/messages.json

Our first job, notify_success, runs when the stage before it (deploy) completes successfully. This is the default for GitLab. Our notify_fail job on the other hand has when: on_failure set, which means it will only run when the stage before it fails. We also set allow_failure: true on both these jobs so that we aren't notified of a failed pipeline if for some reason the notification commands fail. We also set the only: - master option since deploys only happen on the master branch.

We are using Pushover's API to send the message we want in the script area.

With this final stage in place, your pipeline should now look like this:

HASS pipeline overview

Enjoy!

There you have it! Now you can edit your Home Assistant configuration from anywhere you'd like, using your favorite editor, by following three simple steps:

  1. git clone PATH_TO_REPO (if you have not cloned it before)
  2. Edit the configuration
  3. git push -u remote master

Photo by Kevin Bhagat on Unsplash

Install GitLab in 2 minutes

With Ubuntu, Debian, CentOS, openSUSE, and Raspbian packages or from source

Install GitLab Now