Maintainable Secrets

In my last post, I got Continuous Integration and Continuous Deployment (CI/CD) working for my Home Assistant home automation server. It worked at the time, but that was for a very basic configuration of Home Assistant. As I started to set up more components that needed keys or passwords, things started to get hairy.

Luckily, Home Assistant supports a secrets.yaml file, for keeping passwords and keys and stuff in, so you don’t have to have them in your configuration file. The problem is, with CI/CD, where does that secrets.yaml file come from? Lucky again, Gitlab has variables that you can keep secrets in for your project, that it then provides as environment variables on the server where it runs your CI/CD.

So how do you go from secrets stored in environment variables in your CI/CD instance to a secrets.yaml file on you home automation server? A dead simple Bash script stored in my repo that can be run with the CI/CD script has worked really well so far.

#!/bin/bash

cat <<EOF > secrets.yaml
http_password: $HTTP_PASSWORD
zwave_key: $ZWAVE_KEY
home_latitude: $HOME_LATITUDE
home_longitude: $HOME_LONGITUDE
home_elevation: $HOME_ELEVATION
open_weather_api_key: $OPEN_WEATHER_API_KEY
brad_pushbullet_api_key: $BRAD_PUSHBULLET_API_KEY
jess_pushbullet_api_key: $JESS_PUSHBULLET_API_KEY
the_base_url: https://${DEPLOY_HOST}:8123
EOF

Next, one of the add-ons I installed (DuckDNS with LetsEncrypt, for offsite https access to my server), stores its certificates on my Home Assistant server, but the configuration file has to point to them. This causes a problem when the CI server tries to check if my configuration file is ok, because it doesn’t have access to those certificates. Solution? Use my Home Assistant server to check the configuration, since this can be done from the command line.

But, what if the check fails? What will the configuration on my server look like? With the power of git, and a little wrapper script that cleans up after itself, we can solve this problem too.

#!/bin/bash

git fetch
git checkout origin/master
hassio homeassistant check
RESULT=$?
git checkout master
exit $RESULT

This script just does git fetch to get the new changes instead of git pull, so it’s super easy to roll back after we check the configuration. It has to store the exit code of the command to check the configuration, so it can roll back to the current version before exiting with the same status as the configuration check. Couple this with the updated version of the CI script and we’re off to the races.

stages:
  - test
  - deploy

test:
  stage: test
  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:
    - ./generateSecrets.sh
    - ./deploySecrets.sh
    - ssh $DEPLOY_USER@$DEPLOY_HOST "source ~/.bash_profile; cd $DEPLOY_PATH; ./runCheckConfig.sh"

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:
    - ./generateSecrets.sh
    - ./deploySecrets.sh
    - ssh $DEPLOY_USER@$DEPLOY_HOST "source ~/.bash_profile; cd $DEPLOY_PATH; git pull; hassio homeassistant restart"

So far this has been a great way to get my feet wet with some DevOps stuff. And I’d consider what I’ve actually done so far to be much more operations and systems administration than software development on this project.

2 thoughts on “Maintainable Secrets

    1. Agreed. I’m still just using WordPress for now, but once I start doing something different I absolutely will.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s