Installing multiple OctoPrints on Raspberry Pi 3

Test different versions of OctoPrint with the same Raspberry Pi device - Version 2

Introduction

For various reasons (like having an autonomous, network-enabled 3D printer), I like to run OctoPrint on a Raspberry Pi device.

The Raspberry Pi version 3 is a powerful computer based on the BCM2837 Broadcom chip. It contains a quad-core ARM Cortex A53 (ARMv8) cluster running at 1.2GHz.

OctoPrint is created and maintained by Gina Häußge "Foosel". It is written in Python, open-source and published on GitHub, extendable with plugins, and it is compatible with software such as Ultimaker Cura.

This document describes in details the way I like to install and configure a Raspberry Pi 3 running Raspbian and OctoPrint (in fact, more than one instance of OctoPrint), with Supervisor and Nginx. As often, there is more than one way to do things, and this is just one way.

Changes (i.e. version 2)

This is the second iteration of this document. In the previous one, due to a bug, I have to rely on different host names for each instance of OctoPrint. As this bug is now fixed, it is no more necessary.

In this version:

  • each instance of OctoPrint is hosted in a different subfolder, like I originally planned it.
  • it is no more necessary to plug a display and a keyboard during the initial installation of the Raspberry Pi device
  • raspi-config options are set on the command line (without raspi-config interface)
  • I fix some typos and some bugs
  • I have created a simple HTML page with a link for each instance. It is available on GitHub

The first version of this document is still available.

Objectives

I have the following objectives with this installation:

  • No need of a desktop such as LXDE or PIXEL.
  • Run more than one instance of OctoPrint on the same Raspberry Pi device. I want to be able to test Release Candidates of the maintenance branch, test Foosel's development branch and run also my own development version. And if I want to print something important and the current RC has some bugs, I want to be able to use the latest stable release. Of course, only one instance is connected to the 3D printer at the same time (unless you have more than one printer).
  • Run each instance in its own python virtual environment. Some guides use different user accounts. It is not the case here.
  • Run the webcam streamer in its own environment.
  • Start OctoPrint instances and the webcam streamer when the Raspberry Pi boots.
  • Easily manage instances and get detailed logging.

Instances

As explained in the Objectives, I want to run more than one instance of OctoPrint on the same Raspberry Pi device. Here is the list of OctoPrint instances, with their associated branch, python virtual environments, internal ports and description. The table includes also the webcam streamer.

Name Branch Virtual Env Internal Port Description
webcam n/a n/a 6000 WebCam
stable master stable 6001 Current stable release
testing rc/maintenance testing 6002 Maintenance release candidates (next stable)
unstable devel unstable 6003 Current Foosel development version
dev - dev 6099 My current development version

Installing Raspbian 'Stretch' Operating System

  • Download Raspbian from the Downloads page. Since I don't want (I don't need) a desktop such as LXDE or PIXEL, I download RASPBIAN STRETCH LITE.
  • Unzip the file somewhere.
  • There are several tools to write the image. I am using Etcher.
  • Once you have written an image, place a ssh file into the root of the boot partition.
  • Insert the microSD into the Raspberry Pi slot, plug the webcam and plug the power.

IMPORTANT: It is important to place a ssh file into the boot of the microSD. It will instruct the operating system to start a SSH daemon. The content of this file is not important (it can be empty). To add this file, mount the microSD card in your operating system and create the ssh file in the boot partition (not the rootfs one). Note that this step will only work if your network is able to distribute IP addresses (i.e. has a DHCP server). Under macOS, the ssh file can be created with the following command:

touch /Volumes/boot/ssh
diskutil eject /Volumes/boot

Get the IP address of the Raspberry Pi device

There are several ways to get the IP address:

  • Look in the interface of you DHCP server (probably in your router)
  • Use a tool such as nmap to scan the network and find the device

To use nmap, you have to install it. Under macOS (with homebrew):

brew install nmap

Under Debian/Ubuntu:

sudo apt install nmap

Under CentOS:

sudo yum install nmap

Under Windows, you can download nmap installer from the official web site.

If your network is 192.168.1.0, enter the following command (if you do not know your network, use ifconfig / ipconfig):

$ sudo nmap -sP 192.168.1.0/24 | awk '/^Nmap/{ip=$NF}/B8:27:EB/{print ip}'

It will output line(s) such as:

192.168.1.22

This command relies on the fact that the MAC addresses of Raspberry Pi devices start with B8:27:EB (the OUI assigned to the Raspberry Foundation: http://standards-oui.ieee.org/oui.txt).

Check that the port 22 (ssh) is indeed open with the command:

nmap -p 22 192.168.1.22

It replies with something similar to this:

Starting Nmap 7.60 ( https://nmap.org ) at 2017-12-23 15:54 CET
Nmap scan report for 192.168.1.22
Host is up (0.0055s latency).

PORT   STATE  SERVICE
22/tcp open ssh

Nmap done: 1 IP address (1 host up) scanned in 0.05 seconds

If it is not the case (for example: 22/tcp closed ssh), it is probably because you forget to put a ssh file in the root file system.

In the remaining of this document, we will assume that the IP address of the Raspberry Pi device is 192.168.1.22.

Initial login

Once the device has booted, login. The default credentials are pi / raspberry.

ssh pi@192.168.1.22

Initial configuration and updating

The first step is to change the pi password. Choose your own:

passwd

Then update the raspi-config tool to the latest version:

sudo apt-get update
sudo apt-get install raspi-config

Then we will use the raspi-config tool in command-line mode to:

  • set the locale (for example: en_US.UTF8)
  • set the time zone (for example: Europe/Zurich)
  • set the hostname (for example: octoprint1)
  • enable SSH (it is strange, but here 0 means enable)
  • set the memory split between the ARM and the Video (16M for Video)
  • expand the file system to take the entire microSD available space
sudo raspi-config nonint do_change_locale en_US.UTF-8
sudo raspi-config nonint do_change_timezone Europe/Zurich
sudo raspi-config nonint do_hostname octoprint1
sudo raspi-config nonint do_ssh 0
sudo raspi-config nonint do_memory_split 16
sudo raspi-config nonint do_expand_rootfs

Then reboot:

sudo reboot

After a while, connect again by SSH (with the password you set previously).

Update the operating system

Update the system:

sudo apt update
sudo apt -y upgrade
sudo reboot

Install utilities

sudo apt install -y curl aria2 git nano

Notes:

  • In the current version of Raspbian, curl and nano are already installed but it may change in the future so I still include them here.

  • aria2 is a download utility. When it is installed, it is used by pyenv install (instead of curl or wget) and shows a download progress indicator.

NTP client

The NTP client is not enabled by default. To enable it, edit (with sudo nano) /etc/systemd/timesyncd.conf and add the line:

[Time]
Servers=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org 

Enable and start the service:

sudo systemctl start systemd-timesyncd
sudo systemctl enable systemd-timesyncd

tmux

tmux is a terminal multiplexer. I was using screen in the past. Now, I prefer to use tmux for several reasons (such as the default prefix assigned to Ctrl-b instead of Ctrl-a, the status bar, ...)

sudo apt install -y tmux

Create ~/.tmux.conf with the following:

new-session

set -g base-index 1
setw -g pane-base-index 1
set -g default-terminal "tmux"
set -s escape-time 0
set -g history-limit 5000

setw -g automatic-rename on
set -g renumber-windows on

bind-key v split-window -h
bind-key h split-window -v
unbind '"'
unbind %

# Use Shift-arrow keys without prefix key to switch panes
bind -n S-Left select-pane -L
bind -n S-Right select-pane -R
bind -n S-Up select-pane -U
bind -n S-Down select-pane -D

# Switch window
bind -n M-Left next-window
bind -n M-Right previous-window

# Switch session
bind -n M-Up switch-client -n
bind -n M-Down switch-client -p

# Reload tmux config
bind r source-file ~/.tmux.conf \; display-message "Config reloaded..."

bind s copy-mode

This gives the following shortcuts:

Shortcut Description Shortcut Description
Ctrl-b ? Help Ctrl-b c Create window
Ctrl-b d Detach Ctrl-b w List windows
Ctrl-b v Split vertically Ctrl-b n Next window
Ctrl-b h Split horizontally Ctrl-b & Kill window
Ctrl-b x Close current panel (after confirmation) Ctrl-b s Enter copy-mode (and scrolling)
Ctrl-b z Zoom/unzoom current panel
Shift Navigate between window panes Alt previous window
Shift Navigate between window panes Alt Next window
Shift Navigate between window panes Alt previous session
Shift Navigate between window panes Alt Next session

To create a session:

tmux new

To reattach to a session:

tmux attach

To reattach to a session or create a new session if there is none:

tmux attach || tmux new

If using with SSH:

ssh -t pi@192.168.1.22 "tmux attach || tmux new"

SSH Client Configuration

I am using ssh with iTerm2 (under macOS) in order to connect to remote servers. I create a profile with these parameters:

  • Font: Inconsolata 14pt
  • Character Encoding: UTF-8
  • Report Terminal Type: xterm-256color
  • Command: ssh -t pi@192.168.1.22 "tmux attach || tmux new"

Sudo

I never use su. One difference between sudo and su is that with sudo, you provide your current password. With su, you have to provide the password of the new login.

To switch to root:

sudo -i

To switch to another user (for example octoprint):

sudo -iu octoprint

Profiles

Prepare colors for bash ls:

sudo bash -c 'dircolors -p > /etc/dircolors'

Edit ~/.bashrc:

...
force_color_prompt=yes
...
PS1='${debian_chroot:+($debian_chroot)}\[\033[36m\]\u\[\033[m\]@\[\033[32m\]\h:\[\033[33;1m\]\W\[\033[m\]\$ '
...
alias ll='ls -l'
...

To make the changes active:

. ~/.bashrc

Log Viewer

I like to use lnav to read and display the logs in real time:

sudo apt install -y lnav

Then, to display logs (as an example):

sudo lnav /var/log/nginx/* /var/log/supervisor/*

Service accounts

We use one dedicated user octoprint for all OctoPrint instances, one dedicated user webcam for the webcam:

sudo useradd --groups dialout,tty --create-home --system --shell /bin/bash octoprint
sudo useradd --groups video --create-home --system --shell /bin/bash webcam

Note: Accounts octoprint and webcam have no password so you cannot directly login with those accounts and this is what we want here. To login, we use sudo -i.

Permission to execute some commands

We give octoprint the right to execute command to restart OctoPrint and the system. Create the file /etc/sudoers.d/020_octoprint with the command:

sudo visudo -f /etc/sudoers.d/020_octoprint

Enter the following:

Cmnd_Alias SHUTDOWN_CMDS = /sbin/poweroff, /sbin/reboot
Cmnd_Alias SUPERVISOR_COMMANDS = /usr/bin/supervisorctl

octoprint ALL=(ALL) NOPASSWD: SHUTDOWN_CMDS, SUPERVISOR_COMMANDS

Check that everything is OK:

sudo visudo -c

WebCam

I am using a Logitech C270 HD. Even if it is cheap, it supports a resolution of 720p (16:9) and MJPG.

Install MJPG Streamer

Install requirements:

sudo apt -y install libjpeg62-turbo-dev imagemagick libav-tools libv4l-dev cmake

It takes several minutes.

Note: There are other requirements, but they are already installed at this stage.

Connect with webcam identity:

sudo -iu webcam

Download and compile the MJPG Streamer:

git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental
export LD_LIBRARY_PATH=.
make

Test the webcam

To start capturing video:

cd ~/mjpg-streamer/mjpg-streamer-experimental
./mjpg_streamer -i "./input_uvc.so" -o "./output_http.so"

If everything is OK, it displays something like:

 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: -1
 i: Format............: JPEG
 i: TV-Norm...........: DEFAULT
UVCIOC_CTRL_ADD - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_ADD - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt (relative): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Pan/tilt Reset: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Focus (absolute): Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Mode: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at LED1 Frequency: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Disable video processing: Inappropriate ioctl for device (25)
UVCIOC_CTRL_MAP - Error at Raw bits per pixel: Inappropriate ioctl for device (25)
 o: www-folder-path......: disabled
 o: HTTP TCP port........: 8080
 o: HTTP Listen Address..: (null)
 o: username:password....: disabled
 o: commands.............: enabled

The errors are expected and depend of the features of your camera.

Open a navigator and enter the URL: http://192.168.1.22:8080/?action=stream. It displays the video captured by the webcam.

There are plenty of options available. For example to record images in 720p, at the frequency of 25 images per seconds and restrict the binding address to localhost (instead of 0.0.0.0), type:

./mjpg_streamer -o "output_http.so -w ./www -l 127.0.0.1" -i "input_uvc.so -r 1280x720 -f 25"

Note: If you kill mjpg_streamer and start it again immediately, it may fail with errors such as Device or resource busy, Access denied, etc. Sometimes, you have to wait some minutes before restarting mjpg_streamer.

At this stage, you can leave the webcam identity (and go back to pi one):

exit

Installing Cura engine

This part is only important if you want to integrate OctoPrint with the Cura slicer. Unfortunately, OctoPrint does not currently support Cura 2 slicer, only the legacy one. Personally, I never slice in OctoPrint. I am using Cura 2.7 connected to OctoPrint.

sudo -iu octoprint
git clone -b legacy https://github.com/Ultimaker/CuraEngine.git
make -C CuraEngine
exit

It is up to you, but I have decided to let CuraEngine where it is: ~/CuraEngine/build/CuraEngine.

OctoPrint Installation

Install dependencies

sudo apt install -y build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev

PyEnv installer

I like to use pyenv because thank to it, I can precisely manage which version(s) of Python is installed. And thanks to pyenv-virtualenv, a pyenv plugin, I can manage virtual environments.

Download and execute pyenv installer:

sudo -iu octoprint
curl -L https://raw.githubusercontent.com/yyuu/pyenv-installer/master/bin/pyenv-installer | bash

Add the following to the end of ~/.bashrc:

# pyenv
export PATH="~/.pyenv/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"

Refresh the environment:

. ~/.bashrc

Python 2.7

OctoPrint currently supports only Python version 2.7. To get the list of installable Python 2.7 versions, type:

pyenv install --list | grep '^ *2\.7'

If available, you may want to install a more recent version.

pyenv install -v 2.7.14

It takes several minutes.

Download OctoPrint

cd ~
git clone https://github.com/foosel/OctoPrint.git stable

Setup 'stable' Python Virtual Environment and install OctoPrint

cd stable
pyenv virtualenv 2.7.14 stable
pyenv local stable
python setup.py clean
python setup.py install

It takes several minutes.

Create 'stable' configuration folder

mkdir -p ~/.octoprint/stable

OctoPrint Setup Wizard

Since we will have more than one OctoPrint instance, it is important to specify explicitly the base directory. Start OctoPrint with:

cd ~/stable
octoprint serve --basedir ~/.octoprint/stable

After a few seconds, open in a navigator the URL http://192.168.1.22:5000/. The OctoPrint Setup Wizard appears:

  • I recommend to use Access Control and to define a user (such as admin) and a strong password.

  • I recommend to enable Connectivity Check and Plugin Blacklist Processing.

  • Path to CuraEngine: /home/octoprint/CuraEngine/build/CuraEngine. I recommend to import a Cura profile by following the instructions given by the Wizard.

  • Fill in Printer Profile. Do not forget Print bed & build volume, Axes, Hotend & extruder. For my printer (Wanhao i3 Plus), I have to invert the Y axis.

  • Commands:

    • Restart OctoPrint: sudo /usr/bin/supervisorctl restart octoprint:stable
    • Restart system: sudo /sbin/reboot
    • Shutdown system: sudo /sbin/poweroff
  • Webcam & Timelapse Recordings (do not test these settings as Nginx is not yet installed to serve those URLs):

    • Stream URL: http://192.168.1.22/webcam/?action=stream
    • Snapshot URL: http://192.168.1.22/webcam/?action=snapshot
    • Path to FFMPEG: /usr/bin/ffmpeg

When everything is set the way you like, press Ctrl-C to quit OctoPrint process. You can leave the octoprint identity:

exit

Supervisor and Nginx

We need a way to start OctoPrint processes with the right user (octoprint) and python virtual environment (such as stable) and to forward incoming HTTP requests to the right instance. There are several ways to do that. In such situations, I like to use Supervisor to manage processes, Gunicorn as application server and Nginx as reverse proxy server. By coincidence, the logo of Supervisor is also an octopus.

In the particular case of OctoPrint, and if I understand correctly (but I am not 100% sure) how it works, HTTP requests are handled by Tornado. So there is no need for Gunicorn and we simply connect the reverse proxy to OctoPrint instances.

I prefer to use Nginx instead of HAProxy because HAProxy is perfect for load balancing but this is not what we need here.

Install Supervisor

sudo apt -y install supervisor

Edit (sudo nano) /etc/supervisor/supervisord.conf:

[unix_http_server]
file=/var/run/supervisor.sock
chmod=0700
username = supervisor
password = <set your own strong password>

[supervisord]
user = root
logfile=/var/log/supervisor/supervisord.log
pidfile=/var/run/supervisord.pid
childlogdir=/var/log/supervisor

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL  for a unix socket
username = supervisor
password = <set your own strong password>

[include]
files = /etc/supervisor/conf.d/*.conf

Note: Of course, use your own (randomly generated) strong password.

Instances Configuration

Create (sudo nano) /etc/supervisor/conf.d/webcam.conf:

[program:webcam]
directory = /home/webcam/mjpg-streamer/mjpg-streamer-experimental
command = /home/webcam/mjpg-streamer/mjpg-streamer-experimental/mjpg_streamer -o "output_http.so -w ./www -l 127.0.0.1 -p 6000" -i "input_uvc.so -r 1280x720 -f 25"
user = webcam
group = webcam
redirect_stderr = true
stdout_logfile = /var/log/supervisor/webcam.log

Create (sudo nano) /etc/supervisor/conf.d/stable.conf:

[program:stable]
directory = /home/octoprint/stable
command = /home/octoprint/.pyenv/versions/stable/bin/octoprint --basedir "/home/octoprint/.octoprint/stable" --host localhost --port 6001 serve
user = octoprint
group = octoprint
redirect_stderr = true
stdout_logfile = /var/log/supervisor/stable.log

Create (sudo nano) /etc/supervisor/conf.d/octoprint.conf:

[group:octoprint]
programs=stable

Start instances

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status

nginx Installation

sudo apt install -y nginx-full

Log Format

By default, only a few values are logged by Nginx. I prefer to have a little more information in a different order (date and time first). Create (sudo nano) /etc/nginx/conf.d/long-request.conf:

log_format long_request '[$time_local] $remote_addr $remote_user '
                        '$host $server_port $scheme "$request" $args '
                        '"$http_referer" "$http_user_agent" $status $bytes_sent';

Common web site parameters

I like to have my configurations as modular as possible with as few duplications as possible. So instead of repeating gzip parameters and proxy ones, I factor them in configuration files under an include directory. It has the advantage that if we need to modify a parameter, it is modified for all instances at the same time.

Create the include directory:

sudo mkdir /etc/nginx/include

Create (sudo nano) /etc/nginx/include/gzip.conf:

# Enable content compression for text types.
gzip on;
gzip_types text/plain text/css text/xml
           application/x-javascript application/xml
           application/atom+xml text/javascript;
gzip_comp_level 1;
gzip_disable msie6;
gzip_http_version 1.1;

Create (sudo nano) /etc/nginx/include/proxy.conf:

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_http_version 1.1;

client_max_body_size 0;  # 0 to disable it

Note: proxy_http_version 1.1; is important to ensure that OctoPrint works correctly since version 1.3.8 and the update of Tornado to version 4.5.3.

Web apps

Create (sudo nano) /etc/nginx/sites-available/00_octoprint.conf:

upstream webcam   { server 127.0.0.1:6000 fail_timeout=0; }
upstream stable   { server 127.0.0.1:6001 fail_timeout=0; }

server {
    listen [::]:80 default_server deferred ipv6only=off;

    include include/gzip.conf;

        root /var/www/html;

    location = /favicon.ico { access_log off; log_not_found off; }

    location /webcam/ {
        proxy_pass http://webcam/;
    }

    location /stable/ {
        proxy_pass http://stable/;
        include include/proxy.conf;
        proxy_set_header X-Script-Name /stable;
    }

    error_log  /var/log/nginx/octoprint-error.log info;
    access_log /var/log/nginx/octoprint-access.log long_request;
}

nginx_ensite and nginx_dissite commands

These commands mimic those available for Apache. To install them:

cd ~
git clone https://github.com/perusio/nginx_ensite.git
cd nginx_ensite
sudo make install

You can now disable the default site and enable our sites with:

sudo nginx_dissite default
sudo nginx_ensite 00_octoprint.conf
sudo systemctl reload nginx

Firewall

Since our system is ready, we can now filter ports that do not have to be accessible outside the Raspbery Pi device itself. The Operating System contains a host firewall (netfilter/iptables) and The Uncomplicated Firewall (ufw) is a frontend for iptables:

sudo apt install -y ufw

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow http
sudo ufw enable

Testing

Start Nginx:

sudo systemctl start nginx

Open the URL http://192.168.1.22/stable in a web browser. Then click on Login and enter the credentials you define previously.

Under Connection:

  • Serial Port: dev/ttyUSB0
  • Baudrate: 115200
  • Save connection settings

Click Connect. After some seconds, the State changes to Operational.

Click on the Control tab. You should see the video of the webcam.

Cura 2/3 Integration

I use Cura 3 as slicer. It is easy to integrate it with OctoPrint:

  • Start Cura (the version I am using currently is 3.1)
  • Click on SettingsPrinterManage Printers
  • Click on Connect OctoPrint
  • Click on Add:
    • Instance Name: OctoPrint1-Stable
    • IP address or hostname: 192.168.1.22
    • Port Number: 80
    • Path: /stable
  • Click on Open in Browser
  • Login (if necessary) and click on the wrench icon in the toolbar (Settings)
  • Click on API
  • Double click the value after API Key (do not click on the Refresh icon), and copy the value (Ctrl-C or Control-C)
  • Click Cancel
  • Go back in Cura and paste the value into API key
  • Click Connect

You can now send sliced GCODE directly to OctoPrint, pause or abort a print, see the webcam, etc.

Setup another OctoPrint instance: 'testing'

Prepare the environment, download and install OctoPrint (still with the octoprint user identity):

cd ~
git clone https://github.com/foosel/OctoPrint.git testing

cd testing
pyenv virtualenv 2.7.14 testing
pyenv local testing
python setup.py clean
python setup.py install

mkdir ~/.octoprint/testing
exit

We use the stable instance as a template to create a Supervisor configuration:

sudo bash -c "sed 's/stable/testing/g;s/6001/6002/g' /etc/supervisor/conf.d/stable.conf > /etc/supervisor/conf.d/testing.conf"

Edit (sudo nano) /etc/supervisor/conf.d/octoprint.conf to add testing:

[group:octoprint]
programs=stable,testing

Update Supervisor:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl status

Modify the web site (sudo nano /etc/nginx/sites-available/00_octoprint.conf):

...
upstream testing { server 127.0.0.1:6002 fail_timeout=0; }
...
    location /testing/ {
        proxy_pass http://testing/;
        include include/proxy.conf;
        proxy_set_header X-Script-Name /testing;
    }
...

Activate the changes:

sudo systemctl reload nginx

If, when activating the web site, you get an error such as: nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size edit /etc/nginx/nginx.conf and uncomment the line:

server_names_hash_bucket_size 64;

Configuration Wizard

Open the URL http://192.168.1.22/testing in a navigator. The Configuration Wizard for this instance appears:

  • I recommend to use Access Control and to define a user (such as admin) and a strong password.

  • I recommend to enable Connectivity Check and Plugin Blacklist Processing.

  • Path to CuraEngine: /home/octoprint/CuraEngine/build/CuraEngine.

  • Commands:

    • Restart OctoPrint: sudo /usr/bin/supervisorctl restart octoprint:testing
    • Restart system: sudo /sbin/reboot
    • Shutdown system: sudo /sbin/poweroff
  • Webcam & Timelapse Recordings:

    • Stream URL: http://192.168.1.22/webcam/?action=stream
    • Snapshot URL: http://192.168.1.22/webcam/?action=snapshot
    • Path to FFMPEG: /usr/bin/ffmpeg

OctoPrint channel

Go to Settings (the wrench icon in the toolbar) → Software Update. Click on the Plugin Configuration (the wrench icon) and select:

  • OctoPrint version tracking: Release
  • OctoPrint Release Channel: Maintenance RCs

If any Release Candidate is available, OctoPrint displays a message to perform the update.

Differentiate instances

To easily differentiate OctoPrint instances, I change the Appearance parameters:

  • Go to Settings (the wrench icon in the toolbar) → Appearance:

  • Title: I put something like OctoPrint1-Testing or simply Testing

  • Color: I change the color (Green for stable, Orange for testing, Red for Unstable, Violet for dev)

Note: I now prefer to use the Themeify plugin to accomplish a similar effect.

Setup 'unstable' OctoPrint instance

For unstable, proceed exactly like for testing (of course, replace testing by unstable and 6002 by 6003 in the commands) with one difference: just before executing:

python setup.py clean

execute the following command:

git checkout devel

Then run the OctoPrint Configuration Wizard at the URL: http://192.168.1.22/unstable.

Once the instance is installed and configured, go to Settings (the wrench icon in the toolbar) → Software Update. Click on the Plugin Configuration (the wrench icon) and select:

  • OctoPrint version tracking: Commit
  • OctoPrint checkout folder: /home/octoprint/unstable

Plugins

I like to install these plugins:

  • OctoPrint-CustomBackground
  • Detailed Progress
  • EEPROM Marlin Editor
  • Firmware Updater This plugin has to be installed from GitHub (devel branch)
  • Fullscreen Webcam
  • Themeify

For Themeify, I use the following custom Navbar colors:

Instance Color Value
stable Green #4CAF50
testing Orange #FF9800
unstable Red #F44336
dev Purple #9C27B0

Remote Access

Very often, people are asking how to expose OctoPrint to the Internet and secure the access. As it is installed, there is no authentication for some parts such as the webcam. Of course, since we are using a reverse proxy, it is possible to restrict accesses at this level (with apache2-utils and, for example, the auth_basic directive). But, as I understand it, OctoPrint was never designed to be exposed to the Internet and thus, doing so represents a security risk.

I prefer to use a VPN. Most of the routers today do offer such functionality coupled with dynamic DNS. I am using Viscosity as VPN client or the native macOS VPN client, but there are several solutions for all platforms.

Instances web page

We now have several instances of OctoPrint running and accessible using their respective paths such as /stable or /testing. But what happen if we enter the default path / (or just the address of the server)? It displays the default (ugly) page of Nginx. It would be better if we can display a page with a link for each instance of OctoPrint.

Do do that, connect again to the Raspberry Pi by SSH (ssh pi@192.168.1.22):

cd /var/www/html
sudo rm index.nginx-debian.html

You can now add HTML files. For example, you can use the files and images I published on GitHub:

sudo wget https://github.com/andrivet/OctoPrint-Instances/files/1616635/OctoPrint-Instances.zip
sudo unzip OctoPrint-Instances.zip
sudo rm OctoPrint-Instances.zip

The following page is now displayed for the URL http://192.168.1.20/ :

Miscellaneous

PySerial and 250000 baud rate

The version of pyserial currently used by OctoPrint (2.7) is already patched so there is no need to follow the old procedure.

However, some printers are not supporting 250000 baud rate. This is the case of mine (Wanhao Duplicator i3 Plus), probably due to the cheap Arduino-clone used inside. The rate I am using with this printer is 115200.

Future plans

  • Automate the major part of this procedure using Ansible. This way, the complete setup will take only a few clicks and will be reproducible.

  • Troubleshooting: Add some troubleshooting guidelines.

  • pi64: I would like to use a 64-bit operating system since the Raspberry Pi 3 is based on the BCM2837 Broadcom chip and contains a quad-core ARM Cortex A53 (ARMv8) cluster (i.e. a 64-bit processor). Currently, Raspbian is 32-bit only. The pi64 project is created by Bilal Amarni and is based on Debian. It is still experimental and unfortunately, I was not able to get reliable serial communication with pi64.

  • Raspberry Pi Temperature: Build a plugin to display the temperature of the Raspberry Pi itself.