Quick and dirty auto-deployment to Raspberry Pi
Tags: git, ssh, deployment, raspberrypi
Published: 2024-02-27 18:13:51

---
title: Quick and dirty auto-deployment to Raspberry Pi
published: true
date: 2024-02-17 16:07:57 UTC
tags: Git,SSH,deployment,RaspberryPi
canonical_url: https://suda.pl/quick-and-dirty-autodeployment-to-raspberry-pi/
---

 ![Quick and dirty auto-deployment to Raspberry Pi](https://suda.pl/content/images/2024/02/DALL-E-2024-02-17-17.07.02---Create-a-vector-style-illustration-depicting-the-deployment-of-code-to-a-Raspberry-Pi-via-Git.-The-image-should-feature-a-computer-screen-with-the-Git.jpeg)

Some projects require a quick way to deploy code to a Raspberry Pi (or other small device running Linux behing NAT) and it's not critical enough to need things like Kubernetes, Ansible or Docker. It was exactly the case for a small RGB LED matrix we set up at our office to show some KPIs. It was running an OG Raspberry Pi A and we just want to be able to update the code remotly.

### The setup

To make the whole thing a bit easier we decided on a Git based setup. The Pi will keep checking a remote repo for changes and if there are any, it will pull them and restart the `systemd` service driving the display.

### Git setup

The Pi needs to be able to access the repository therefore we needed to add the public SSH key of the Pi as a Deploy key:

1. Generate a new key on the Pi (only if it doesn't have one yet) with:

<!--kg-card-begin: shell-->
```
$ ssh-keygen -t ed25519
$ cat ~/.ssh/id_ed25519.pub
```
<!--kg-card-end: code-->

2. Copy the resulting key and paste it in **Settings** -> **Deploy keys** -> **Add deploy key** in your GitHub repo

3. Clone the repo on the Pi via ssh

### Main application service

1. First you need to define a `systemd` service for your main application:

<!--kg-card-begin: ini-->
```
[Unit]
Description=rgb-matrix

[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/home/pi/rgb-matrix/run.sh
WorkingDirectory=/home/pi/rgb-matrix
StandardOutput=append:/home/pi/rgb-matrix/stdout.log
StandardError=append:/home/pi/rgb-matrix/stderr.log
User=root
Group=root

[Install]
WantedBy=multi-user.target
```
<!--kg-card-end: code-->

In our case the application has to run as a `root` but in your case there might be a better user for that. Once created, you need to enable it:

<!--kg-card-begin: code-->
```
$ sudo ln -s ${PWD}/rgb-matrix.service /etc/systemd/system/rgb-matrix.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable rgb-matrix.service
$ sudo systemctl start rgb-matrix.service
```
<!--kg-card-end: code-->
### Auto-deployment service

Now we need a small script that will be periodically checking the remote repo:

<!--kg-card-begin: code-->
```
#!/bin/bash

# Configuration
SERVICE_NAME="rgb-matrix" # The name of the systemd service you want to restart

# Function to check for updates and pull them
check_and_pull() {
    git fetch origin

    # Check if there are updates available
    if ! git diff --quiet origin/main; then
        echo "Changes detected, pulling updates..."
        git pull
        echo "Updates pulled successfully."

        # Restart the systemd service
        echo "Restarting the service: $SERVICE_NAME..."
        systemctl restart "$SERVICE_NAME"
        echo "Service restarted successfully."
    fi
}

# Main loop to periodically check for updates
while true; do
    check_and_pull
    # Wait for a specified interval before checking again
    sleep 60 # Checks every 60 seconds, adjust as needed
done

```
<!--kg-card-end: code-->

Similarily to the main application, we need to create a `systemd` service for the watcher:

<!--kg-card-begin: code-->
```
[Unit]
Description=watcher

[Service]
Type=simple
Restart=always
RestartSec=5
ExecStart=/home/pi/rgb-matrix/watcher.sh
WorkingDirectory=/home/pi/rgb-matrix
StandardOutput=append:/home/pi/rgb-matrix/watcher-stdout.log
StandardError=append:/home/pi/rgb-matrix/watcher-stderr.log
User=root
Group=root

[Install]
WantedBy=multi-user.target
```
<!--kg-card-end: code-->

and enable it as well:

<!--kg-card-begin: code-->
```
$ sudo ln -s ${PWD}/watcher.service /etc/systemd/system/watcher.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable watcher.service
$ sudo systemctl start watcher.service
```
<!--kg-card-end: code-->
### Done

Now any changes pushed to the remote repo will get automatically fetched and deployed. This of course does not take into account any migrations, installation of dependencies, rollbacks etc. but that's ok :)