In this article I will describe how to setup OctoPrint based on OctoPi on a Raspberry Pi 3 for multiple printers. For every printer a seperate OctoPrint instance with a different port must be started. If you want to use more than one webcam, you also have to start seperate instances of MJPG-Streamer for each webcam. I have also added a link to another article where I give a short overview about how you can switch on and off your printers with the use of a n-channel relay module. First we set up OctoPrint for just one printer and after that works, for multiple printers and webcams.
Necessary Components
To run OctoPrint on a Raspberry Pi not much components are needed.
- Raspberry Pi 3 (RPi) or newer
- MicroSD card with 8GB or more
- Power supply with at least >=2.0A output current
- A webcam if you like to see what your printer is doing
- A printed case for the RPi
If you want to set it up by using a connected HDMI Monitor and a USB keyboard (I will!) you also need the following
- HDMI monitor
- HDMI cable
- USB keyboard
That’s all you need to setup OctoPrint on your RPi. If you want to be able to switch your printers on and off you can also have a look at this article: „How to switch on and off your 3d printer with your Raspberry Pi“
Where to start with ?
The first step is to install the OctoPi image on your SD card. There are a lot of tutorials out there which shows how to do it. The steps are quite straight forward if you use a Windows OS.
- Download OctoPi image: http://octoprint.org/download/
- Download Win32 Disk Imager: https://sourceforge.net/projects/win32diskimager/ or Etcher: https://etcher.io/
- Insert your SD card in your SD card reader
- Choose the tool of your choice, open the *.img file and write it to the SD card.
If you are using a Linux OS then I recommend this site: https://www.raspberrypi.org/documentation/installation/installing-images/linux.md
After installing the firmware onto the SD card we should be able to do some configurations in the octopi-network.txt and octopi.txt file on the boot partition on the SD card. This is the only folder you can see under a Windows system. I had some problems making some configurations with that file. I wanted to create a wifi connection with a static IP but nothing worked as it should because I did a mistake. If you make any mistake with your wifi connection in that file before the first boot, you have to correct it later directly in your system. So it seems to me, that these files just used once after the first boot for creating the wifi connection. I recommend to not make any configurations for a wifi connection in that file. If you connect your RPi via an ethernet cable to your router you don’t have to change anything if getting a IP over DHCP is okay for you. Therefore a DHCP server must be running in you network.
Connect a monitor via a HDMI cable to your RPi and also connect a USB keyboard to it. It is then possible to do the configuration locally without using the octopi-network.txt file or a SSH connection at this point.
Set up the wifi connection
The configuration for the interfaces in this case for the wifi connection is done in /etc/network/interfaces
sudo nano /etc/network/interfaces
The wlan0 section gets modified to this:
auto wlan0allow-hotplug wlan0iface wlan0-raspbian inet manual wpa-conf /etc/wpa_supplicant/wpa_supplicant.confpre-up iw dev wlan0 set power_save offpost-down iw dev wlan0 set power_save onwireless-power off
or for a static IP address to this
auto wlan0allow-hotplug wlan0iface wlan0-raspbian inet static address 192.168.0.225 netmask 255.255.255.0 gateway 192.168.0.254 wpa-conf /etc/wpa_supplicant/wpa_supplicant.confpre-up iw dev wlan0 set power_save offpost-down iw dev wlan0 set power_save onwireless-power off
I also added some lines (the last 3) to prevent the wifi module from going into power saving mode.
This was helpful because I got some weird connection problems. The rest of the interfaces file is untouched.
Some additional german information about how to prevent the wifi module from shutting down to power save mode can be found here: https://www.elektronik-kompendium.de/sites/raspberry-pi/1912231.htm
Because we are using a WPA encrypted wifi connection we have to modify the /etc/wpa_supplicant/wpa_supplicant.conf file.
sudo nano /etc/wpa_supplicant/wpa_supplicant.conf
Add a network which includes the SSID and the PSK of your wifi connection.
network={ ssid="beehive" psk="supersecurekey"}
After a reboot the RPi should be able to connect to your router and you should be able to connect to it via SSH. Under a Windows systemyou can use PuTTY or KiTTY for that.
Basic configuration
Some basic configurations like „Expanding Filesystem“, „Change User Password“, „Localisation Options“ and more can be done by using the tool raspy-config.
sudo raspi-config
After you expanded the file-system and have finished with the raspi-config configurations it is time to setup your OctoPrint user, your printer and the rest of the OctoPrint configuration. Therefore use your favourite browser to connect to the OctoPrint webserver: IP assigend by your router e.g. http://192.168.x.y
The next steps are nearly selfexplaining but there are also a lot of tutorials out there. A german tutorial can be found here: http://selbstgedruckt.de/octoprint_teil1/
Connect the different printers to the RPi
Now it is your turn! Connect your printers, set up its profiles, play around with OctoPrint. Set up every printer you have and create a working profil for every. At this stage you are then able to plug in all of your printers but only able to connect to and print with one at once. During the first printer is printing, you are not able to connect to a second one without disconnecting the connection to your actually printing printer! When the first one has finished its job, than you are able to disconnect and connect to the second and print with this one. This is the reason why we need a seperate instance for every printer, more about that later.
Create some udev rules for individual printer device names
It can be a mess to find the corresponding device for a specific printer. The device naming /dev/ttyUSB0 is generally made in a sequential order. So in this case the first printer plugged in will get /dev/ttyUSB0 the second one /dev/ttyUSB1 and so on. It is not guaranteed, that this naming is the same after a reboot. So we will use udev to create some symlinks to devices which will have the same name and correspond to the same printer before and after a reboot. I use ttyMKC for my core printer and ttyANET for my Anet printer.
First we have to determine the differences of the respective devices, so we can give udev some attributes so it can differ between the devices (printers). If you are lucky your devices differ in a lot of attributes. It can also be that they are nearly equal or complete equal! In my case only the attributes „KERNELS“ and „devpath“ where different.
To determine the differences you can do it manually by looking at the outputs of udevamd for the different devices. The following command is for /dev/ttyUSB0.
udevadm info -q all -n /dev/ttyUSB0 --attribute-walk
You can also pipe the outputs to files and the use diff to get the differences.
udevadm info -a -n /dev/ttyUSB0 > devInfoUSB0udevadm info -a -n /dev/ttyUSB1 > devInfoUSB1diff -u devInfoUSB0 devInfoUSB1
Then we create a file 99-usb.rules for the udev rules
cd /etc/udev/rules.d/ sudo nano 99-usb.rules
and insert the following two lines of code. Each line is a rule for each printer we want to use later. These two lines will only work in my case! You have to use the attributes which differ in your case! Not every attribute has to be different, but at least one attribute must be different!
SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{devpath}=="1.3", SYMLINK+="ttyANET"SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{devpath}=="1.5", SYMLINK+="ttyMKC"
Some more informations about the udev rules can be found here: https://txlab.wordpress.com/2016/06/14/udev-rules-for-ttyusb-devices/
Setting up one more instance of OctoPrint
When your printers print over OctoPrint like they should and every printer has its individual device names e.g. /dev/ttyMKC and /dev/ttyANET we can go further to the next step, the setup of another instance of OctoPrint. Therefore 4 steps are necessary:
- Copy OctoPrint directory
- Copy and modify OctoPrint2 config script
- Copy and modify OctoPrint2 init script
- Add new OctoPrint2 init script to autostart
First we copy the OctoPrint directory
cp -R /home/pi/.octoprint /home/pi/.octoprint2
next copy the OctoPrint configuration script /etc/default/octoprint to /etc/default/octoprint2
sudo cp /etc/default/octoprint /etc/default/octoprint2
and modify the port and add a new basedir the changes look like this:
PORT=5001DAEMON_ARGS="--host=$HOST --port=$PORT --basedir /home/pi/.octoprint2/"
Then copy the init script
sudo cp /etc/init.d/octoprint /etc/init.d/octoprint2
and modify the content a bit.
sudo nano /etc/init.d/octoprint2
There have to made some changes at the top of this file! Change every name from „octoprint“ to „octoprint2“ and „OctoPrint“ to „OctoPrint2“ but leave the line „DEAMON=/usr/bin/octoprint“ untouched!
My file looks like this:
#!/bin/sh ### BEGIN INIT INFO# Provides: octoprint2# Required-Start: $local_fs networking# Required-Stop:# Should-Start:# Should-Stop:# Default-Start: 2 3 4 5# Default-Stop: 0 1 6# Short-Description: OctoPrint2 daemon# Description: Starts the OctoPrint daemon with the user specified in# /etc/default/octoprint2.### END INIT INFO # Author: Sami Olmari PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/binDESC="OctoPrint2 Daemon"NAME="OctoPrint2"DAEMON=/usr/bin/octoprintPIDFILE=/var/run/$NAME.pidPKGNAME=octoprint2SCRIPTNAME=/etc/init.d/$PKGNAME...
OctoPi uses systemctl, so it is important to reload the daemon list after a new init script is added.
sudo systemctl daemon-reload
We also want that this starts automatically after booting, so we update the rc.d
sudo update-rc.d octoprint2 defaults
To start the service manual you can use
sudo /etc/init.d/octoprint2 start
To check if the octoprint2.service has been added successfully to systemctl run
systemctl status octoprint2.service
That’s it for the moment, if you don’t get any errors it works like it should.
Take a beer and make a break.
HaProxy Configuration
OctoPi uses HaProxy as a reverse proxy for mapping and security reasons. If HaProxy is disabled and not used
sudo /etc/init.d/haproxy stop
the webservers of the OctoPrint instances will be reachable on port 5000 and the second on port 5001 (e.g. http://192.168.x.y:5000)
I don’t recommend to disable HaProxy because you will loose a neadful security barrier. But for now let it disabled.
If you use multiple OctoPrint instances and you want to make them reachable as a directory name instead of using a port, this can and must be done using HaProxy. Therefore modify the /etc/haproxy.cfg for your needs.
First make a backup of the original file.
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.old
Then open the config file.
sudo nano /etc/haproxy/haproxy.cfg
My haproxy.cfg looks like this and is configured for 3 printers also a CTC printer on port 5002:
global
maxconn 4096
user haproxy
group haproxy
log 127.0.0.1 local1 debug
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
option http-server-close
option forwardfor
maxconn 2000
timeout connect 5s
timeout client 15min
timeout server 15min
frontend public
bind *:80
bind 0.0.0.0:443 ssl crt /etc/ssl/snakeoil.pem
option forwardfor except 127.0.0.1
use_backend webcam if { path_beg /webcam/ }
use_backend mkc if { path_beg /mkc/ }
use_backend anet if { path_beg /anet/ }
use_backend ctc if { path_beg /ctc/ }
default_backend webcam
backend mkc
reqrep ^([^\ :]*)\ /mkc/(.*) \1\ /\2
option forwardfor
server octoprint1 127.0.0.1:5000
acl needs_scheme req.hdr_cnt(X-Scheme) eq 0
reqadd X-Scheme:\ https if needs_scheme { ssl_fc }
reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc }
reqadd X-Script-Name:\ /mkc
backend anet
reqrep ^([^\ :]*)\ /anet/(.*) \1\ /\2
option forwardfor
server octoprint1 127.0.0.1:5001
acl needs_scheme req.hdr_cnt(X-Scheme) eq 0
reqadd X-Scheme:\ https if needs_scheme { ssl_fc }
reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc }
reqadd X-Script-Name:\ /anet
backend ctc
reqrep ^([^\ :]*)\ /ctc/(.*) \1\ /\2
option forwardfor
server octoprint1 127.0.0.1:5002
acl needs_scheme req.hdr_cnt(X-Scheme) eq 0
reqadd X-Scheme:\ https if needs_scheme { ssl_fc }
reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc }
reqadd X-Script-Name:\ /ctc
backend webcam
reqrep ^([^\ :]*)\ /webcam/(.*) \1\ /\2
server webcam1 127.0.0.1:8080
errorfile 503 /etc/haproxy/errors/503-no-webcam.http
For each backend except for the webcam backend, it is important to define the correct X-Script-Name! I wasted a lot of time finding this necessary configuration parameter.
How to use a second webcam?
The first webcam which is connected gets the device name /dev/video0 the second the device name /dev/video1 and so on. We run into the same trouble when we started connecting the different printers to the RPi. We have to create udev rules to get a device name which is the same every time we restart the RPi.
To determine the differences we pipe the outputs to a file and the use diff to get the differences.
udevadm info -a -n /dev/video0 > /home/pi/devVideo0udevadm info -a -n /dev/video1 > /home/pi/devVideo1diff -u /home/pi/devVideo0 /home/pi/devVideo1
Then modify the 99-usb.rules file.
cd /etc/udev/rules.d/sudo nano 99-usb.rules
and add the following two lines of code. Each line for each webcam we want to use. These two lines will only work in my case! You have to use the attributes which differ in your case! Be carefull with the devpath attributes. Only use them if find no other attributes which differ or if you now what you are doing!
SUBSYSTEM=="video4linux", ATTRS{idVendor}=="0ac8", ATTRS{idProduct}=="301b", ATTRS{devpath}=="1.4", SYMLINK+="videoANET"SUBSYSTEM=="video4linux", ATTRS{idVendor}=="046d", ATTRS{idProduct}=="0821", ATTRS{devpath}=="1.2", SYMLINK+="videoMKC"
Now we can to start the default instance of Mjpg-Streamer with the device parameter -p /dev/videoMKC and a second one with the device parameter -p /dev/videoANET. We can now make our settings in the daemon. First make a backup and the a copy for the second instance.
cd /root/bin/sudo cp webcamd webcamd.oldsudo cp webcamd webcamd2sudo nano webcamd
Because we use two daemons for each camera one, we cannot make our configuration in the /boot/octopi.txt file. We have to do the modifications direct in the deamon file but that’s okay. We add the -d parameter and the device to the camera_usb_options variable and the port parameter to camera_http_options. This then looks like this:
camera_usb_options="-d /dev/videoMKC -r 640x480 -f 10"camera_http_options="-p 8080"
We also make the changes in the file of the second daemon.
sudo nano webcamd2
The modified files looks like this:
camera_usb_options="-d /dev/videoANET -r 640x480 -f 10"camera_http_options="-p 8081"
Take care at this point, because every webcam configuration parameter which is set in the /boot/octopi.txt file will be used for every webcam daemon you start!
Also a modified copy of /etc/default/webcamd is needed. So we make one and modify it.
cd /etc/default/sudo cp webcamd webcamd2sudo nano webcamd2
and change the DAEMON and LOG variable to this:
DAEMON=/root/bin/webcamd2LOG=/var/log/webcamd2.log
We also have to create a new /etc/init.d/ script for that second daemon. We choose the original on and copy it and then modify the copy.
cd /etc/init.d/sudo cp webcamd webcamd2sudo nano webcamd2
The head of the modified webcamd2 file looks like this:
#!/bin/sh
### BEGIN INIT INFO # Provides: webcamd2 # Required-Start: $local_fs networking # Required-Stop: # Should-Start: # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: webcam2 daemon # Description: Starts the OctoPi webcam daemon with the user specified config in
# /etc/default/webcamd. ### END INIT INFO
# Author: Gina Haeussge
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DESC="Webcam2 Daemon" NAME="webcamd2" DAEMON=/root/bin/webcamd2 USER=pi PIDFILE=/var/run/$NAME.pid PKGNAME=webcamd2 SCRIPTNAME=/etc/init.d/$PKGNAME LOG=/var/log/webcamd2.log ...
Now we come slowly but surely to an end but have to execute some more commands.
OctoPi uses systemctl like said before so we reload thedaemon list again.
sudo systemctl daemon-reload
We also want that this daemon starts automatically during booting, so we update the rc.d
sudo update-rc.d webcamd2 defaults
To start the service manual you can use
sudo /etc/init.d/webcamd2 start
To check if the webcamd2.service has been added successfully to systemctl run
systemctl status webcamd2.service
Another steps follows 🙂 … We have to make the new instance visible behind HaProxy.
sudo nano /etc/haproxy/haproxy.cfg
and add a new backend at the end of file
backend webcam2 reqrep ^([^\ :]*)\ /webcam2/(.*) \1\ /\2 server webcam1 127.0.0.1:8081 errorfile 503 /etc/haproxy/errors/503-no-webcam.http
and a new line under „frontend public„
use_backend webcam2 if { path_beg /webcam2/ }
restart haproxy
sudo /etc/init.d/haproxy restart
and your webcam should be reachable under http://192.168.x.y/webcam2/
To use the second webcam stream directly in your OctoPrint web-interface you also have to adapt the stream path
/webcam2/?action=stream
in your OctoPrint Webcam & Timelapse settings.
If you want to create an instance for a third printer or webcam, just repeat the steps for the second ones
Update: I found small mistake in haproxy.cfg so below is working one forme with one webcam
root@octopi:/home/pi# more /etc/haproxy/haproxy.cfg
global
maxconn 4096
user haproxy
group haproxy
log 127.0.0.1 local1 debug
defaults
log global
mode http
option httplog
option dontlognull
retries 3
option redispatch
option http-server-close
option forwardfor
maxconn 2000
timeout connect 5s
timeout client 15min
timeout server 15min
frontend public
bind *:80
bind 0.0.0.0:443 ssl crt /etc/ssl/snakeoil.pem
option forwardfor except 127.0.0.1
use_backend webcam if { path_beg /webcam/ }
use_backend octoprint if { path_beg /octoprint/ }
use_backend octoprint2 if { path_beg /octoprint2/ }
default_backend webcam
backend octoprint
reqrep ^([^\ :])\ /octoprint/(.) \1\ /\2
option forwardfor
server octoprint1 127.0.0.1:5000
acl needs_scheme req.hdr_cnt(X-Scheme) eq 0
reqadd X-Scheme:\ https if needs_scheme { ssl_fc }
reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc }
reqadd X-Script-Name:\ /octoprint
backend octoprint2
reqrep ^([^\ :])\ /octoprint2/(.) \1\ /\2
option forwardfor
server octoprint1 127.0.0.1:5001
acl needs_scheme req.hdr_cnt(X-Scheme) eq 0
reqadd X-Scheme:\ https if needs_scheme { ssl_fc }
reqadd X-Scheme:\ http if needs_scheme !{ ssl_fc }
reqadd X-Script-Name:\ /octoprint2
backend webcam
reqrep ^([^\ :])\ /webcam/(.) \1\ /\2
server webcam1 127.0.0.1:8080
errorfile 503 /etc/haproxy/errors/503-no-webcam.http
root@octopi:/home/pi#
Other source just to get logic of the configuration can be found here, but it was not working for my 1.3.11 version
You also need to edit the restart setting. If not changed then when the second instance does a restart it incorrectly restarts the first instance. You have to go in to Settings->Octoprint->Server->Restart and change the service name.