Connecting OctoPrint boxes to Karmen

Filip Vařecha
May 21, 2020 · 9 min read

You might be wondering why Karmen cloud service doesn’t yet natively support OctoPrint boxes whilst our Karmen Pill companion is built upon it. Strange, isn’t it? In this article, I will explain the reasons behind it and also introduce our new tool to connect any OctoPrint box without a hassle.

Karmen with its simple online access solves what many OctoPrint users just can’t achieve easily: having their box accessible on the road literally from anywhere. The problem here is networking. Kicking off a new OctoPi with RPi4 isn’t much of an effort but exposing it safely via the internet is an entirely different beast. There are several ways you do it but all of them require substantial amount of work. Here are some options one can come up with quickly:

  • Port forwarding on your router — relatively easy albeit not exactly safe without further SSL configuration.
  • VPN—simple to use (if you’re okay with turning VPN connection on and off just to see how your prints are doing), much harder to configure.
  • SSH tunneling—rather straight forward, not so much on you phone though.

Enter websocket-proxy

At Karmen, we needed to find more elegant solution that wouldn’t need any configuration on the users end. We don’t want our users configuring their router port forwarding just to use their Karmen Pills! That’s why we came up with our open source websocket-proxy.

It takes care of the difficult networking part by inverting the logic. Instead of talking directly to your box and needing to slip through all those routers and firewalls, Karmen talks to a websocket-proxy server which your box also connects to. This effectively avoids exposing the box out to the wild! Each proxy connection has an identifier which allows Karmen to easily talk to gazillions of boxes. It only needs to know the right connection identifier. And yes, that’s the key you use when registering a Karmen Pill with Karmen as described in the docs.

Good, just tell me how to connect my OctoPrint

Sorry for drifting away from the original topic! It was necessary for you to understand how you actually connect your OctoPrint instance. Simply said, you need to establish a connection with the websocket-proxy server Karmen cloud service has access to. Up until now, we only had a private endpoint for connecting Karmen Pills. This changes now as we’ve exposed another and public proxy server for connecting other devices like OctoPrint installations.

Also, we’ve created the karmen-octoprint-connector utility that simplifies setting this up as much as possible. You will need to install connector utility directly on your OctoPrint box and make sure it’s up & running at all times—keeping the connection alive. But before you do so, you first need to get yourself a valid connection key.

Getting the connection key

Obtaining a connection key is simple. Sign in to Karmen, navigate to the printer addition dialog under the Settings menu item and choose Other device in the I’m adding field instead of the default Karmen Pill.

Fresh connection key will be generated for you in the Connection key field value. Simply copy it to your clipboard with the Copy button right next to it. Don’t forget to name your printer and save it even though it won’t report as connected just yet.

Using OctoPrint with the access control enabled? If so, make sure to also provide Karmen with an API key under the Advanced options on the printer addition screen. See our docs for more information if unsure how to get one.

Now that you have the key at your hand, time has come to run the connector and enable Karmen to take control. There are two basic ways you can deploy it:

  • Using Docker—often the easiest option, Docker is rather widespread
  • Using npx—useful when you have NPM already installed

Using Docker

The obvious requirement here is having the Docker daemon available on your machine. In case you happen to run an Debian-based OctoPi, you can install it with just a few shell commands:

# Install docker
sudo apt install software-properties-common -y
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh

# Allow pi default user to manage docker
sudo usermod -aG docker pi
# Reboot
sudo reboot

If you’re on different OS, there are plenty of resources out there to help you: just Google “install docker on [your OS]”. Once you have Docker installed, running karmen-octoprint-connector boils down to executing the following one-liner:

# Fill your key
karmen_key="your key"
docker run --init --net=host fragaria/karmen-octoprint-connector:latest connect $karmen_key

This will run our multi-arch Docker image (compatible with both arm and amd64). Just make sure you use the right connection key. If everything worked out, you should soon see something like this:

OctoPrint on non-80 port

Previous setup assumes you have your OctoPrint running on the default port 80. If that’s not your case, you need to tell the connector to use another port instead:

docker run --init --net=host fragaria/karmen-octoprint-connector:latest connect -f http://localhost:80 $karmen_key

Provide full URL of the address you want to forward. Most of the time, it will be http://localhost:[port] where only the port is different.

Using npx

In case you prefer going with npm(installing it is out of scope of this article), the principle stays same, only the command changes:

# Fill your key
karmen_key="your key"
npx karmen-octoprint-connector connect $karmen_key

A more resilient setup

Examples above are useful when you just wanna play around and try Karmen out. If you conclude you want Karmen to be your daily driver, it’s a good idea to make the OctoPrint connector deployment more resilient. Let’s install a systemd service to take care about running the connector daemon in the background. It will also ensure it’s started automatically when your machine reboots. We will only cover the Docker-based scenario here but the setup for npx-based option will be similar.

In order to run the connector using systemd, we need a service config file. Start by creating a blank file at /etc/systemd/system/karmen-octoprint-connector.service. Here is our recommended service configuration:

# A systemd script to run karmen-octoprint-connector resiliently.
# This script expects docker to be available, make sure you instal
# it first.
[Unit]
Description=Karmen OctoPrint connector
After=docker.service
Requires=docker.service
After=network.target
[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker stop %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=/usr/bin/docker pull fragaria/karmen-octoprint-connector
ExecStart=/usr/bin/docker run --rm --init --net=host --name %n fragaria/karmen-octoprint-connector:latest connect --url $SERVER_URL --forward $FORWARD $KEY
Restart=always
RestartSec=1000
User=pi
Group=pi
Environment=PATH=/usr/bin:/usr/local/bin
EnvironmentFile=/etc/karmen-octoprint-connector.conf
[Install]
WantedBy=multi-user.target

Let’s just quickly go through it. First, the Unit section states that our service requires Docker and networking to be available before starting the connector service: this ensures all the necessary services are started before attempting to run the connector itself. Second, in theService section, there are multiple pre-execution steps (ExecStart pragmas):

  1. Stop existing connector container in case there’s one already running.
  2. Delete container if it’s already present which forces the container to be recreated.
  3. Pull a fresh release of the connector image from Docker Hub.

Note that the first and second steps are denoted with ExecStartPre=-. This means our service start won’t be considered failed should these housekeeping steps fail. The reason for that is that they’re actually likely to fail at least once: during the first run when no previous containers are present on your machine.

The rest is rather straightforward: we use the same command as we did previously and just make sure it runs under pi user and group—this service configuration is meant for OctoPi where pi user is the default. Feel free to modify this to fit your scenario.

Note that our main command references some environment variables. These will be provided by the environment file which holds the connector configuration. Create this file at /etc/karmen-octoprint-connector.conf. It should look like this:

KEY=--connection-key--
SERVER_URL=https://cloud.karmen.tech/connector/v1/
FORWARD=http://localhost

Make sure you provide the connection key and address to forward. No need to modifySERVER_URL—it already points to our public websocket-proxy instance. Now that we have all configuration we needed, we just enable our service and start it:

sudo systemctl daemon-reload
sudo systemctl start karmen-octoprint-connector.service

First launch might take a bit longer as the service needs to pull the Docker image. But shorty, you can verify it’s running with:

systemctl status karmen-octoprint-connector.service

It should report something similar to the following:

● karmen-octoprint-connector.service - Karmen OctoPrint connector
Loaded: loaded (/etc/systemd/system/karmen-octoprint-connector.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-05-12 04:10:55 CEST; 7h ago
Process: 10786 ExecStartPre=/usr/bin/docker stop karmen-octoprint-connector.service (code=exited, status=1/FAILURE)
Process: 10796 ExecStartPre=/usr/bin/docker rm karmen-octoprint-connector.service (code=exited, status=1/FAILURE)
Process: 10804 ExecStartPre=/usr/bin/docker pull fragaria/karmen-octoprint-connector (code=exited, status=0/SUCCESS)
Main PID: 10829 (docker)
Tasks: 11 (limit: 4915)
Memory: 25.2M
CGroup: /system.slice/karmen-octoprint-connector.service
└─10829 /usr/bin/docker run --rm --init --net=host --name karmen-octoprint-connector.service fragaria/karmen-octoprint-connector:latest connect ...

After a minute or two, Karmen will realise your printer is now online and automagically begin to manage it. You can now navigate to cloud.karmen.tech and see your printer for yourself! But… where the hell is your slick video feed?

The video feed issue

No worries, we will fix this real quick. We just need to modify OctoPrint configuration to expose the video feed on a different URL. Karmen will realise that immediately as it reads the OctoPrint config via its REST API.

Problem with default configuration is that it uses port 8080 (namely, configuration points to 127.0.0.1:8080). Remember we configured our connector utility to forward port 80? That’s right, port 8080 isn’t forwarded and thus, Karmen won’t be able to access it. Fortunately, OctoPrint comes up bundled with haproxy which already proxies whatever webcam has to offer on 127.0.0.1:80/webcam. Therefore, we just need to tell OctoPrint to use that address instead. Navigate to your OctoPrint settings and on the Webcam & Timelapse page and set the Snapshot URL to http://127.0.0.1/webcam/?action=snapshot.

Wondering why we’re modifying the snapshot URL when video is what we’re after? Karmen favors snapshots over standard video feed because the the mjpeg-streamer OctoPrint uses is very hungry bandwith-wise. Snaphosts work equally well and produce a lot less traffic. Save you smartphone data plan for the important stuff like Facebook!

Adjusting the bitrate and resolution

Almost there! The last piece of the puzzle is to set the proper bitrate and resolution for your webcam. Karmen works best with 640x480px, 5 FPS and a slightly adjusted cam bitrate.

Start by modifying your /boot/octopi.txt. Look for camera_usb_options or camera_raspi_options and change it (or change both just to make sure it works either way) to tell the webcam to use the suggested resolution and frame rate:

camera_usb_options="-r 640x480 -f 5"
camera_raspi_options="-x 640 -y 480 -fps 5"

Now, let’s modify the bitrate. Create a/etc/systemd/system/webcam-bitrate.service file and put following content there:

[Unit]
Description=Sets webcam bitrate
After=webcamd.service[Service]
User=pi
Group=users
ExecStart=/usr/bin/v4l2-ctl --set-ctrl video_bitrate=5000000
[Install]
WantedBy=multi-user.target

Since the command for setting bitrate itself wouldn’t persist the settings for future reboots, we need to create a systemd service to take care of that. Make sure the service is loaded:

sudo systemctl daemon-reload

Now just reboot your OctoPi box with reboot and celebrate! Having finished all the necessary steps, it’s now time to enjoy managing your printers from anywhere! You should see your printer in Karmen with a working video feed ready to accept commands over the wire.

Karmen3D

Developers meet 3D print engineers—talking about printer management in the cloud.

Filip Vařecha

Written by

Long-term web developer that embraces agile approach to building things as he see it as the only one actually working.

Karmen3D

Karmen3D

Developers meet 3D print engineers—talking about programming and especially about Karmen: a cloud-hosted and open-source 3D printer management app.

Filip Vařecha

Written by

Long-term web developer that embraces agile approach to building things as he see it as the only one actually working.

Karmen3D

Karmen3D

Developers meet 3D print engineers—talking about programming and especially about Karmen: a cloud-hosted and open-source 3D printer management app.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store