GitHub Actions is a mature and extremely popular CI/CD tool. It allows you to create workflows for software deployment, testing, building ... whatever. In GitHub Actions you build your workflows by using blocks automating common tasks called Actions.
One of those building blocks is now Husarnet Action! ๐
Learn how you can leverage Husarnet Action in your workflow to deploy code to devices with no public IP like laptop, Raspberry Pi, some random VM sitting on your server or even to ESP32 microcontrollers. All by adding a few lines to your existing GitHub Actions yaml
file.
Find Husarnet Action in the GitHub marketplace:
Use Casesโ
With Husarnet Action you can treat any device like it has a public IP. Thanks to that it enables CI/CD pipelines not only for servers but also directly for IoT / edge devices.
We have prepared two GitHub repository templates allowing you to test Husarnet Action in practical use cases:
Example project | Description |
---|---|
esp32-internet-ota | A template project with CI/CD for Over The Air (OTA) firmware update to ESP32 via the Internet, directly from GitHub workflow. Read more... |
ga-rsync-demo | Showing how to copy files / build artifacts from GitHub workflow directly to Raspberry Pi (or other edge / IoT devices) with rsync. Read more... |
You will find detailed instructions showing how to run those projects in their repo README.md
files, but in the next section I will focus only on GitHub workflow yml
files to show you how Husarnet Action is used.
ESP32 OTA over the Internet (deploy to ESP32)โ
Let's use Husarnet Action for deploying firmware to ESP32 powered devices over the Internet.
We have prepared esp32-internet-ota template project where both source code for ESP32 and GitHub workflow is ready to use (just define your own repository secrets).
Here's how GitHub workflow used to deploy to ESP32 looks like:
name: ESP32 OTA update
on:
push:
branches:
- 'main'
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Connecting the GitHub workflow to Husarnet VPN network
uses: husarnet/husarnet-action@v2
with:
join-code: ${{ secrets.HUSARNET_JOINCODE }}
- name: ESP32 software reset
run: curl -X POST 'http://${{ secrets.HUSARNET_HOSTNAME }}:8080/reset'
- name: Installing platformio
run: pip3 install -U platformio
- name: Building a firmware for ESP32
run: |
export SSID=${{ secrets.WIFI_SSID }}
export PASS=${{ secrets.WIFI_PASS }}
export JOINCODE=${{ secrets.HUSARNET_JOINCODE }}
export HOSTNAME=${{ secrets.HUSARNET_HOSTNAME }}
pio run
- name: Uploading a firmware to ESP32
run: >
curl --http0.9 -# -v
-H 'Accept: */*'
-H 'Accept-Encoding: gzip, deflate'
-H 'Connection: keep-alive'
-F "MD5="$(md5sum "${{ github.workspace }}/.pio/build/esp32dev/firmware.bin" | cut -d ' ' -f 1)""
-F 'firmware=@${{ github.workspace }}/.pio/build/esp32dev/firmware.bin'
'http://${{ secrets.HUSARNET_HOSTNAME }}:8080/update'
- name: Stop Husarnet
run: sudo systemctl stop husarnet
What is going on in the workflow:
Connecting our workflow to the same Husarnet network as the ESP32 board we want to flash (using
HUSARNET_JOINCODE
). ESP32 VPN connection needs to be present while starting that workflow, so the first firmware update is needed to be done manually. Full instruction is in README.Installing PlatformIO and building a firmware with 4 environment variables provided as repository secrets:
GitHub repo secret description WIFI_SSID
andWIFI_PASS
ssid (name) and password for the Wi-Fi network that will be hardcoded in firmware for ESP32 (we replace the whole firmware, so we need to also provide network credentials) HUSARNET_JOINCODE
a secret key you will get from your Husarnet Dashboard account at https://app.husarnet.com allowing you to connect new devices to your Husarnet network. It looks like fc94:...:932a/xhfqwPxxxetyCExsSPRPn9
HUSARNET_HOSTNAME
a handy name for your ESP32 allowing other hosts to reach it, without using its Husarnet IPv6 address (eg. ping6 my-awesome-esp32
instead ofping6 fc94:f632:c8d9:d2b6:ad18:ed16:ed7e:9f3f
Building a firmware (
firmware.bin
file) using PlatformIOUploading the firmware over the Internet to ESP32 with
curl
.Turning off Husarnet network (even when a workflow finishes its job, before it quits it need some time during which it is still Husarnet connected)
After all these steps new firmware is uploaded to ESP32 and it boots immediately after that on the remote device.
Direct OTA deployment to a fleetโ
By combining workflow with matrix of different job configurations you can flash remotely not only a single ESP32 by, the whole fleet at once.
Just make a few modifications in the ota-update.yml
file:
name: ESP32 OTA update
on:
push:
branches:
- 'main'
jobs:
build:
runs-on: ubuntu-20.04
strategy:
matrix:
esp32-id:
- 'motion-sensor-1'
- 'motion-sensor-2'
- 'motion-sensor-3'
- 'motion-sensor-4'
- ...
- 'motion-sensor-n'
steps:
...
- name: Building a firmware for ESP32
run: |
export SSID=${{ secrets.WIFI_SSID }}
export PASS=${{ secrets.WIFI_PASS }}
export JOINCODE=${{ secrets.HUSARNET_JOINCODE }}
export HOSTNAME=${{ matrix.esp32-id }}
pio run
- name: Uploading a firmware to ESP32
run: >
curl --http0.9 -# -v
-H 'Accept: */*'
-H 'Accept-Encoding: gzip, deflate'
-H 'Connection: keep-alive'
-F "MD5="$(md5sum "${{ github.workspace }}/.pio/build/esp32dev/firmware.bin" | cut -d ' ' -f 1)""
-F 'firmware=@${{ github.workspace }}/.pio/build/esp32dev/firmware.bin'
'http://${{ matrix.esp32-id }}:8080/update'
...
According to official docs: A job matrix can generate a maximum of 256 jobs per workflow run. That means you can update the firmware concurrently for up to 256 ESP32 powered devices at once. Of course you can create multiple workflows to multiply that number. ESP32 OTA over the internet is pretty simple with GitHub Actions & Husarnet Action.
Thanks to that your code and remote firmware update setup are covered by a version control in a single GitHub repository. That's a true Infrastructure as Code way of handling IoT fleets.
Deploying to edge devices (deploy to Raspberry Pi)โ
If you want to deploy build artifacts, or just copy random files from your GitHub workflow to the edge devices like Raspberry Pi or other SBC / headless system, you can use Husarnet Action to enable that as well.
In the example we will use rsync to copy files from our workflow to Raspberry Pi.
name: Deploy to Raspberry Pi
on:
push:
workflow_dispatch:
jobs:
copy-to-remote-host:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Connecting to Husarnet VPN network
uses: husarnet/husarnet-action@v2
with:
join-code: ${{ secrets.HUSARNET_JOINCODE }}
- name: Wait until connection with peer is established (with 2m timeout)
run: ping6 -w 120 -c 1 ${{ secrets.HUSARNET_TARGET_HOSTNAME }}
- name: Install SSH private key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_PRIVATE_KEY }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: Rsync over SSH
run: >
rsync -vr
./files/
root@${{ secrets.HUSARNET_TARGET_HOSTNAME }}:/root/files
- name: Stop Husarnet
run: sudo systemctl stop husarnet
What is going on in the workflow?
- Connecting our workflow to the same Husarnet network as Raspberry Pi (using
HUSARNET_JOINCODE
). - Making sure that peer-to-peer connection with the target host (Raspberry Pi) is established.
- Installing private SSH key allowing GitHub workflow SSH access to remote Raspberry Pi (
SSH_PRIVATE_KEY
repository secret need to be defined). The public SSH key of the key pair needs to be added to/etc/known_hosts
in Raspberry Pi. - Using
rsync
to send files from./files
folder of GitHub workflow to/root/files
directory on remote Raspberry Pi (using Husarnet hostname).
Pretty simple. Of course for a full example and step by step instructions visit the project repo.
Summaryโ
In this blog post I have introduced Husarnet Action for GitHub Actions that allows you to deploy build artifacts, trigger the event or send files to devices that don't have a public nor static IP address like your laptop, Raspberry Pi, NAS drive, or ESP32 microcontroller.
I have presented two demo projects showcasing how Husarnet Action works in ... well, action :) :
- ESP32 over the air update just from your GitHub workflow (deploy to ESP32)
- sending/deploying files to edge devices using rsync (deploy to Raspberry Pi)
By combining presented GitHub Actions workflows (powered by Husarnet Action) with matrix of different job configurations, you can deploy your code to the whole fleet at once.
Now you can treat any device like it was a normal server (from your GitHub workflow point of view).
Automate deployment of code to edge devices with Husarnet Action For GitHub Actions ๐
If you have any questions or want to discuss something related to this blog post, let's do it at Husarnet Community Forum.