OctoPrint

Aujourd'hui, on installe OctoPrint en docker sur notre RaspberryPi, avec un reverse proxy qui a du SWAG.

OctoPrint

OctoPrint - ou OctoPi dans sa version pour Raspberry Pi - est un logiciel libre et open source publié sous la licence publique GNU AGPL, permettant de contrôler son imprimante 3D depuis un navigateur Web.

Un monument du genre qui a fait de multiples petits tel OctoFarm pour ne citer que lui, réunissant une communauté forte et créative.


Sommaire

  1. Prérequis
  2. Firmwares VideoCore
  3. OctoPrint
  4. SWAG - NGINX
  5. App : OctoPod
  6. Conclusion
  7. Ressources

Prérequis

  • Être coutumier de Docker
  • Avoir pré-installé Docker est Docker-compose
  • Être coutumier de l'utilisation d'un serveur web permettant de faire un reverse proxy et/ou être familier avec son utilisation. Dans le présent article, nous utilisons Nginx via l'image docker SWAG qui rendra accessible votre OctoPi en https avec ces certificats émanants de Let's Encrypt (ou ZeroSSL, au choix).
  • Si vous souhaitez rendre accessible depuis Internet OctoPrint, votre serveur hôte doit être accessible sur le port 80 et le port 443. Typiquement si vous utilisez un Raspberry Pi dans un réseau local, vous devrez faire un port forwarding depuis votre routeur (si c'est possible) vers l'IP locale de votre hôte, en s'assurant de rendre cette IP fixe.

Le présent tutoriel a été réalisé sur un Raspberry Pi 3 Model B Plus Rev 1.3 sous Raspbian GNU/Linux 10 (buster).

AVERTISSEMENT : Avant de rendre accessible votre RaspberryPi accessible depuis Internet, assurez-vous de le SECURISER, ceci dit n'est pas anodin. Si vous suivez le présent tutoriel, vous le faites en connaissance de cause. Je ne saurai être tenu pour responsable en cas de problème.

Répertoire de travail

Dans le présent tutoriel nous aurons comme répertoire de travail /docker :

  • Nous le créons avec :
sudo mkdir /docker
  • On s'assurera que notre utilisateur ai les droits avec :
sudo chown -R <user>:<user> /docker
  • L'arborescence ressemblera à ceci :
/docker/octoprint
├── octoprint
├── octoprint-packages
└── docker-compose.yml

Firmwares VideoCore

Si vous utilisez une webcam ou une Camera Pi, il est important de s'assurer d'avoir son kernel et notamment ses librairies de VideoCore à jour.

Si au démarrage de votre container Octoprint vous obtenez une erreur concernant MJPG streamer, assurez-vous de mettre à jour vos librairies vidéos comme présenté en aval de cet d'article. Pour ma part, j'ai du le faire afin de voir apparaitre le device /dev/video0 utilisé dans la configuration de OctoPrint.

Si tout est bon, vous obtiendrez ceci :

octopi       | MJPG Streamer Version.: 2.0
octopi       |  i: Using V4L2 device.: /dev/video0
octopi       |  i: Desired Resolution: 640 x 480
octopi       |  i: Frames Per Second.: -1
octopi       |  i: Format............: JPEG
octopi       |  i: TV-Norm...........: DEFAULT
octopi       |  o: www-folder-path......: /usr/local/share/mjpg-streamer/www/
octopi       |  o: HTTP TCP port........: 8080
octopi       |  o: HTTP Listen Address..: (null)
octopi       |  o: username:password....: disabled
octopi       |  o: commands.............: enabled

Mise à jour des firmwares (optionnel)

AVERTISSEMENT : Par défaut, rpi-update clone le firmware depuis le master, il s'agit donc de prereleases. Les versions préliminaires (prereleases) du logiciel ne sont pas garanties de fonctionner. Cela peut laisser votre système peu fiable ou même complètement cassé. Il ne doit pas être utilisé dans le cadre d'un processus de mise à jour régulier.

Vous pouvez changer la branche par défaut avec la commande suivante et pourquoi, utiliser la branche stable des firmwares :

sudo BRANCH=stable rpi-update

Validez et redémarrez votre RaspberryPi :

sudo reboot now

Mettons maintenant à jour notre kernel, nos firmwares, etc... exécutez la commande :

sudo rpi-update
  • rpi-update effectue d'abord une sauvegarde avant de procéder à la mise à jour. En cas de besoin, vous pouvez rollback (documentation).
  • La mise à jour prendra quelques minutes. Il vous faudra redémarrer votre Raspberry Pi avec sudo reboot now avant de poursuivre.

OctoPrint

Le coeur du tutoriel, la mise en place d'OctoPrint.

Docker Compose

On commence en créant un fichier nommé docker-compose.yml dans le répertoire de votre choix (ici /docker/octoprint), avec votre éditeur de texte favori (nano ?).

Il vous faudra adapter selon vos besoins et votre infrastructure, notamment :

  • Volumes (persistents) : le chemin est relatif au répertoire courant, ici /docker/octoprint/. Nos données, configurations seront donc conservées dans /docker/octoprint/octoprint et nos plugins dans /docker/octoprint/octoprint-packages. Les plugins installés depuis l'interface d'OctoPrint seront alors persistents.
  • Devices : afin de pouvoir intéragir avec les ports USB /dev/ttyUSB0 (votre imprimante 3D) et votre webcam /dev/video0 (pour faire simple), il va falloir rendre accessible le tout à votre conteneur.
  • Environment - User ID et Group ID : ici PGID=100 et PUID=1000. Pour connaitre ceux de l'utilisateur souhaité, utilisez la commande id elle vous retournera l'UID et le GID de votre utilisateur courant (1000 par défaut pour le premier utilisateur du système).
  • Environment - Timezone : Gardons nos pendules à l'heure et définissons la timezone, ici TZ=Europe/Paris.
  • Environment - ENABLE_MJPG_STREAMER : Activons l'option pour pouvoir utiliser le stream webcam, en la mettant sur true.
  • Ports : Décommentez les deux lignes Ports si vous souhaitez utiliser le container OctoPrint sans reverse proxy. Le port 80 sera alors publié et rendra accessible votre container sur le port 80 (http).
  • Networks : définissez un réseau docker en le nommant comme bon vous semble. Ce network sera nécessaire si vous utilisez OctoPrint derrière un reverse proxy fonctionnant lui aussi sous Docker. Ils devront être dans le même réseau docker. Pour créer le réseau, saisissez docker network create <network>. Si vous n'utilisez pas de reverse proxy, Il est inutile de spécifier un réseau, vous pourez dès lors supprimer ou commenter ces lignes.

Passons à la pratique :

  • on créé le répertoire - mkdir /docker/octoprint
  • on créé le fichier - nano /docker/octoprint/docker-compose.yml
  • et on y colle ce qui suit :
version: '3'

services:
  octoprint:
    image: octoprint/octoprint
    container_name: octoprint
    restart: unless-stopped
    devices:
       - /dev/video0:/dev/video0 # Default Video device
       - /dev/ttyUSB0:/dev/ttyUSB0 # USB device > your 3Dprinter
    volumes:
     - ./octoprint:/octoprint/octoprint
    # This volume will make the plugin permanent during restarts or image upgrade
     - ./octoprint-packages:/octoprint/plugins/lib/python3.8/site-packages # persistent plugins
# Uncomment two lines (ports) below to use container OctoPrint docker without reverse proxy     
#    ports:
#     - 80:80
    environment:
     - PUID=1000
     - PGID=100
     - TZ=Europe/Paris # timezone
     # uncomment the lines below to ensure camera streaming is enabled when you add a video device
     - ENABLE_MJPG_STREAMER=true
    networks:
     - <network>

networks:
  <network>:
    external:
      name: <network>

Votre OctoPrint est configuré, vous pouvez le démarrer en mode attaché :

docker-compose up
  • Si le container démarre correctement et que vous n'avez pas d'erreur, fermez-le avec la combinaison de touches ctrl + C puis redémarrez-le en mode détaché avec :
docker-compose down; docker-compose up -d

Techniquement votre OctoPrint est fonctionnel et vous pouvez y accéder depuis votre navigateur web (si vous avez publié le port 80 de votre conteneur), en saisissant l'adresse IP ou le hostname de votre Raspberry Pi (par défaut raspberrypi.local). Saisissez la commande hostname -r pour la connaitre, le cas échéant. Profitez-en pour créer votre compte utilisateur.

Si vous souhaitez utiliser OctoPrint uniquement en local, pas depuis Internet et si vous n'avez pas d'autres services nécessitant d'utiliser le port 80, vous pouvez en rester là. Sinon, poursuivez et installez un serveur web.

Configuration : Webcam

En ce qui concerne la webcam et sa configuration, vous devrez vous assurez de vos paramètres. Dans vos paramètres, sélectionnez Webcam & Timelapse et vérifiez les réglages suivants:

  • URL de vidéo - /webcam/?action=stream
  • URL de photo - http://127.0.0.1:8080/?action=snapshot
  • Emplacement de FFMPEG - /usr/bin/convert

OctoPrintWebcam

SWAG : NGINX

En démarrant le container OctoPi, vous pourriez y accéder sans problème depuis votre navigateur web en vous rendant sur l'adresse IP locale de votre Raspberry Pi ou même en tapant le hostname de celui-ci, par défaut pour Raspbian c'est raspberrypi.local.

A savoir :

  • si vous souhaitez héberger d'autres services qui nécessitent également les ports 80/443, il peut-être nécessaire de recourir à un serveur web avec un reverse proxy, qui sera le seul à écouter sur les ports 80/443 et redirigera vers le bon service.
  • si vous souhaitez rendre accessible votre RaspberryPi depuis Internet, vous allez devoir chiffrer vos connexions en HTTPS avec un certificat et mettre en place un reverse proxy.

Aussi vous pourrez alors définir d'autres services sous différents nom de domaine dans le réseau local (ex.: homebridge.pi, adguard.pi, heimdal.pi, etc) avec une petite réécriture DNS. C'est toujours plus classe que d'accéder à ses services en redéfinissant les ports de service.


Je vous propose deux images docker pour Nginx, selon le cas de figure dans lequel vous vous trouvez :

  • linuxserver/SWAG - si vous souhaitez rendre accessible votre octoprint depuis Internet ? Utilisez cette image et suivez ce chapitre du tutoriel.
  • linuxserver/NGINX - si vous souhaitez simplement héberger plusieurs services en local avec un reverse proxy. La configuration du serveur nginx est assez similaire à celle avec l'image SWAG, il vous faudrait ajouter différentes configurations notamment celle du proxy. Nous ne détaillerons pas ici la configuration avec cette image.

Docker-compose : Linuxserver / SWAG

On passe à la configuration de NGINX, au travers l'image linuxserver/SWAG. Nous nous attarderons surtout sur la configuration de NGINX. Aussi je me dois de vous la présenter et vous expliquer pourquoi j'ai opté pour cette solution.

SWAG - Secure Web Application Gateway - est une image docker développée par LinuxServer, embarquant NGINX, Certbot (Let's Encrypt), PHP et Fail2Ban. SWAG permet également d'utiliser la connexion avec HTTP Auth, LDAP via leur image ldap-auth, et Authelia (2 facteurs). Bref, je vous recommande.


Il vous faudra adapter selon vos besoins et votre infrastructure, notamment :

  • le volume persistent : ici le chemin est relatif et monte le volume dans le répertoire courant ./config
  • Déterminez le réseau docker <network>. Les containers SWAG et Octopi doivent être dans le même réseau.
  • Spécifiez les variables d'environnement selon vos besoins : EMAIL, URL, MAXMINDDB_LICENSE_KEY (à lire : doc)

A savoir que vous pouvez utiliser l'host de votre Raspberry Pi (ex.: raspberrypi.local), il faudra le spécifier dans la configuration du site baptisé octoprint, mais pas dans le docker-compose.yml de SWAG (ne complétez pas alors les variables URL, XTRA_DOMAINS ou SUBDOMAINS). Cela peut notamment vous être utile si vous ne souhaitez pas rendre accessible depuis Internet mais uniquement à votre réseau local.


  • on créait le répertoire - mkdir /docker/swag
  • on créait le fichier - nano /docker/swag/docker-compose.yml
  • et on y colle ce qui suit, en adaptant selon nos besoins :
version: '3'

services:
  swag:
    image: ghcr.io/linuxserver/swag
    container_name: swag
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Europe/Paris
      - URL=<domain.tld>
      - SUBDOMAINS=
      - VALIDATION=http
      - EMAIL= <email> #optional
      - ONLY_SUBDOMAINS=false #optional
      - EXTRA_DOMAINS=<extra.domain.tld> #optional
      - MAXMINDDB_LICENSE_KEY=<maxminddb key>
      - STAGING=false #optional
    volumes:
      - ./config:/config
    ports:
      - 443:443
      - 80:80 #optional
    restart: unless-stopped
    networks:
      - <network>

networks:
  <network>:
    external:
      name: <network>
  • On se place dans le répertoire - cd /docker/swag
  • On enregistre et on démarre le container en mode attaché - docker-compose up
  • Une fois que les certificats Let's Encrypt ont été créés et que tout fonctionne, on peut arrêter le container avec ctrl + c. On s'assurera d'arrêter complétement le container et de supprimer les volumes non persistents en tapant docker-compose down

Reverse Proxy

  • Par défaut le DNS resolver de Docker est 127.0.0.11 (loopback), il suffit alors de faire une requête avec le nom du container, qui est défini ici par set $upstream_app octopi. Pour que la requête aboutisse, il est nécessaire que le container octopi se trouve dans le même réseau docker que SWAG.

Si vous souhaitez rendre accessible depuis Internet votre OctoPi, assurez-vous d'avoir à votre disposition un domaine de second niveau ou un sous-domaine, que vous aurez déclaré dans la zone DNS de votre provider. Songez aussi à effectuer un Port forwarding vers votre Raspberry Pi des ports 80 et 443.


  • Créez le fichier - nano /docker/swag/config/nginx/site-confs/octopi
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name octopi.domain.tld;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        # enable the next two lines for http auth
        auth_basic "Restricted";
        auth_basic_user_file /config/nginx/htpasswd/.octopi;

        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_app octopi;
        set $upstream_port 80;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

    location /control {
        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_app octopi;
        set $upstream_port 80;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    }

}

http auth

Lorsque vous vous connectez à votre OctoPrint, il vous demande de saisir vos identifiants ou d'en créer si c'est la première fois que vous le démarrez. C'est bien. Mais on peut aller plus loin en sécurisant la connexion avant même d'accéder à OctoPrint, au niveau de Nginx et du reverse proxy.
Mettons en place une authentification via htpasswd.

  • Installons apache2-utils :
sudo apt update && sudo apt install apache2-utils
  • On créé un fichier mot de passe en spécifiant un utilisateur <user> :
htpasswd -c /docker/swag/config/nginx/htpasswd/.octopi <user>
  • Le prompt vous demandera de saisir à deux reprises un mot de passe de votre choix. Faites-le et conservez-le. Lorsque vous vous rendrez sur l'adresse redirigeant vers votre OctoPi, il vous seront demandé.
  • Dans le fichier de configuration octopi ci-dessus, vous aurez sans doute remarqué les lignes concernant auth_basic. C'est ici que nous précisons le chemin vers le fichier mot de passe que nous nous apprêtons à créé. Dans notre cas le chemin (interne au container) est /config/nginx/htpasswd/.octopi.

Tout est en place, (re-)démarrons notre container SWAG pour appliquer les changements :

docker-compose down;docker-compose up -d

Vous pouvez maintenant accéder à votre instance OctoPrint en vous rendant à l'adresse que vous avez défini, dans notre exemple https://octopi.domain.tld. Un username et un password vous serons demandés par NGINX avant de pouvoir accéder à OctoPrint.

Si vous le souhaitez, vous pouvez conserver un bookmark sur votre navigateur avec l'adresse suivante : https://<user>:<password>@octopi.domain.tld.

App : OctoPod

Petit Bonus ! Nombre d'applications compatibles avec OctoPrint permettent de controler son imprimante depuis une tablette ou un smartphone. J'utilise depuis pas mal de temps l'application OctoPod pour iOS, iPadOS, WatchOS et tvOS, développé par Gaston Dombiak (Github).

OctoPod utilise la clé API générée par OctoPrint. Vous trouverez celle-ci dans Paramètres > API. (Re-)Générez-la si nécessaire et scannez le QRcode avec l'application OctoPod depuis Réglages > Imprimante > Ajouter une imprimante.

OctoPrint_API

Le truc sympa, c'est qu'OctoPod permet de spécifier si un http auth est requis, en détaillant le <user> et le <password> (spécifiés au chapitre http auth) :

OctoPod_Settings

Plugin

Un plugin pour OctoPod existe et permet d'envoyer des notifications Push à votre appareil. : https://plugins.octoprint.org/plugins/octopod/

Conclusion

Voilà ! Vous venez d'installer OctoPrint via Docker et vous l'avez rendu accessible depuis internet. Théoriquement, cela vous permet de garder un oeil sur vos impressions depuis n'importe ou dans le monde, cependant je me dois de vous rappeler quelque chose d'essentiel : On ne laisse jamais une impression sans surveillance, sans possibilité d'intervenir physiquement et en personne, en cas de besoin.

Rendre OctoPrint accessible depuis internet me permet surtout d'accéder à mes fichiers (STL, timelapses, etc) ou tout simplement d'y accéder en données mobiles avec mon smartphone, plutôt que depuis mon réseau local.

Par précaution, je ne peux que trop vous recommander d'installer une alarme à incendie (il en existe d'ailleurs des connectées) à proximité de votre imprimante et à utiliser une prise de courant connectée, qui vous permettra d'arrêter à distance votre imprimante en coupant le courant.
Pour ma part j'utilise la prise TP-Link HS110 combinée aux plugins TpLinkAutoShutdown et TPLinkSmartplug qui permettent d'activer/désactiver la prise connectée en cas de besoin.

N'hésitez pas à m'offrir du retour et à poser vos questions en commentaire ! Merci.

Ressources