Quick and dirty auto-deployment to Raspberry Pi
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:
$ ssh-keygen -t ed25519
$ cat ~/.ssh/id_ed25519.pub
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:
[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
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:
$ 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
Auto-deployment service
Now we need a small script that will be periodically checking the remote repo:
#!/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
Similarily to the main application, we need to create a systemd
service for the watcher:
[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
and enable it as well:
$ 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
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 :)