Installing OctoPrint on a Raspberry Pi the Hard Way

Not that it's actually hard, it's just not the easy way.

If you want to set up OctoPrint on a Raspberry Pi, usually you just flash OctoPi and you're good to go. But maybe you want to have a little more of a handle on what's going on with the install. Perhaps, like me, you really didn't like the OctoPrint service running as the pi user.

Start with a fresh flash of Raspberry Pi OS Lite. You can install one of the versions with a desktop if you want, but for me the whole point is to control the machine from elsewhere. This guide was written using Raspberry Pi OS Buster.

Make sure your package repos are updated and everything is in a current state, then install the Python prerequisites:

sudo apt update
sudo apt upgrade
sudo apt install -y python3 python3-pip python3-venv

Next create a virtual environment for OctoPrint. The location here is one of the major differences from OctoPi. We're going to install it in /usr/local as a system service rather than in the pi user's home directory.

sudo python3 -m venv /usr/local/octoprint

To install OctoPrint, we need to activate the virtual environment we just created. We also need to perform the install as root, as we're in /usr/local. If we activate the venv and use sudo, the sudo command won't pick up on the aliases set by the venv. Instad, we need to switch to the root user, activate the venv, and install OctoPrint. Installing OctoPrint may take a minute or two.

sudo su
cd /usr/local/OctoPrint
source bin/activate
pip3 install octoprint
exit

Next we'll add a service user for OctoPrint. We'll add it to the tty and dialout groups so it can access the serial ports.

sudo useradd --system --shell=/usr/sbin/nologin octoprint
sudo usermod -a -G tty octoprint
sudo usermod -a -G dialout octoprint

Since we're running OctoPrint as a service instead of in the pi user's home folder, we'll want to set up system-level config and output folders. We'll give the octoprint user ownership of these folders, as OctoPrint needs to write to them:

sudo mkdir /etc/octoprint
sudo chown -R octoprint.octoprint /etc/octoprint/
sudo mkdir /var/octoprint
sudo chown -R octoprint.octoprint /var/octoprint

To set up OctoPrint as a system service, we'll download the OctoPrint service definitions from the OctoPrint website and modify it to use our pathing and user:

wget https://github.com/OctoPrint/OctoPrint/raw/master/scripts/octoprint.service && sudo mv octoprint.service /etc/systemd/system/octoprint.service
sudo nano /etc/systemd/system/octoprint.service

Change the file to look like this:

[Unit]
Description=OctoPrint
After=network-online.target
Wants=network-online.target

[Service]
Environment="LC_ALL=C.UTF-8"
Environment="LANG=C.UTF-8"
Type=exec
User=octoprint
ExecStart=/usr/local/OctoPrint/bin/octoprint --config /etc/octoprint/config.yml --basedir /var/octoprint/ serve

[Install]
WantedBy=multi-user.target

The most important part is the user key which tells our service to use the service user we created, and the ExecStart key which tells it to use the service, config, and output folders we set up.

Finally, we can start the service using systemctl and verify that it's running:

sudo systemctl daemon-reload
sudo systemctl start octoprint
sudo systemctl status octoprint

Ideally, you'll see something like the following:

● octoprint.service - OctoPrint
   Loaded: loaded (/etc/systemd/system/octoprint.service; disabled; vendor preset: enabled)
   Active: active (running) since Mon 2021-10-11 21:57:58 BST; 1h 33min ago
 Main PID: 2770 (octoprint)
    Tasks: 12 (limit: 2059)
   CGroup: /system.slice/octoprint.service
           └─2770 /usr/local/OctoPrint/bin/python3 /usr/local/OctoPrint/bin/octoprint --config /etc/octoprint/config.yml --basedir /var/octoprint/ serve

You should now be able to access the OctoPrint UI at port 5000 on your Raspberry Pi's IP.