Spoolman behind a Traefik-Proxy in the internal network

German version below:

Spoolman is a great too to track your filament usage and Sebastian already described the setup. I’m also running Spoolman in my internal network. The software got multiple user interfaces or integrations so that you can use it standalone in a browser or integrate a widget into Klippers User interface.

The integration into Moonraker (the Web Interface for Klipper) currently doesn’t have the ability to provide any credentials for Moonrakers Spoolman integration to authenticate against Spoolman.

If you want to expose Spoolman to the Internet to check your filament usage from outside your homework you surely want authentication. Spoolman doesn’t offer any user management at all at the moment. So you have to user a normal web server or proxy to add some authentication.

In my personal setup I’m using Traefik reverse proxy to expose Spoolman running in a Docker container to the internet and handle the SSL certificates. SSL is also required to make use of Spoolmans feature to scan QR codes of your spools.

The requirements in my setup are: do not require a password when requests come from the local network (192.168.1.0/24); do require HTTP Basic authentication when request comes from the outside Internet.

This way the integration into my Klipper setup doesn’t require authentication but accessing Spoolman from the internet does.

While this would be relatively straightforward with Apache HTTPD it was a bit tricky with Traefik.

My solution is to define two http.routers in Traefik for Spoolman. One for access from the internal network:

- "traefik.http.routers.spoolman-internal.rule=( Host(`spoolman.example.net`) && ClientIP(`192.168.1.0/24` ))"

and one for access from the outside Internet:

- "traefik.http.routers.spoolman.rule=Host(`spoolman.example.net`) && !ClientIP(`192.168.1.0/24` )"
- "traefik.http.routers.spoolman.entrypoints=websecure"

Both http.routers then can have their own Traefik middlewares section to add authentication or not.

My whole Spoolman docker-compose.yaml looks like this:

version: '3.8'
services:
  spoolman:
    image: ghcr.io/donkie/spoolman:latest
    restart: unless-stopped
    labels:
       - "traefik.enable=true"
       - "traefik.http.routers.spoolman-internal.rule=( Host(`spoolman.example.net`) && ClientIP(`192.168.1.0/24` ))"
       - "traefik.http.routers.spoolman-internal.entrypoints=websecure"
       - "traefik.http.routers.spoolman.rule=Host(`spoolman.example.net`) && !ClientIP(`192.168.1.0/24` )"
       - "traefik.http.routers.spoolman.entrypoints=websecure"
       - "traefik.http.routers.spoolman.tls=true"
       - "traefik.http.routers.spoolman.priority=2"
       - "traefik.http.routers.spoolman.tls.certresolver=letsencrypt"
       - "traefik.http.routers.spoolman-internal.tls.certresolver=letsencrypt"
       - "traefik.http.routers.spoolman.middlewares=auth-users"
       - "traefik.http.routers.spoolman-internal.tls=true"
       - "traefik.http.routers.spoolman-internal.priority=1"
       - "traefik.http.routers.spoolman.service=svc-spoolman"
       - "traefik.http.routers.spoolman-internal.service=svc-spoolman"
       - "traefik.http.services.svc-spoolman.loadbalancer.server.port=8000"
       - "traefik.http.middlewares.auth-users.basicauth.users=admin:$$2U$$07$$K3XvlqQOC3ScMoRqOIQ50elXe.QByrAvpvmaDp9yj0oaA4LOLiCE6"
    networks:
      - web
    volumes:
      # Mount the host machine's ./data directory into the container's /home/app/.local/share/spoolman directory
      - type: bind
        source: ./data # This is where the data will be stored locally. Could also be set to for example `source: /home/pi/printer_data/spoolman`.
        target: /home/app/.local/share/spoolman # Do NOT change this line
    ports:
      # Map the host machine's port 7912 to the container's port 8000
      - target: 8000
        published: 7912
        protocol: tcp
        mode: host
    environment:
      - TZ=Europe/Stockholm # Optional, defaults to UTC

networks:
  web:
    name: web
    external: true

German version:

Spoolman ist ein echt tolles Tool, um den Filamentverbrauch zu verfolgen, und Sebastian hat die Einrichtung bereits beschrieben.
Ich verwende Spoolman auch in meinem internen Netzwerk. Die Software hat mehrere Benutzeroberflächen oder Integrationen, so dass man sie eigenständig in einem Browser verwenden oder ein Widget in Klippers Benutzeroberfläche integrieren kann.

Die Integration in Moonraker (das Web-Interface für Klipper) bietet derzeit keine Möglichkeit, Anmeldedaten für Moonrakers Spoolman-Integration bereitzustellen, um sich gegenüber Spoolman zu authentifizieren.

Wenn Sie Spoolman dem Internet aussetzen wollen, um Ihre Filamentnutzung von außerhalb Ihres Hauses zu überprüfen, brauchen Sie sicherlich eine Authentifizierung. Spoolman bietet zur Zeit keine Benutzerverwaltung an. Sie müssen also einen normalen Webserver oder Proxy verwenden, um eine Authentifizierung hinzuzufügen.

In meinem persönlichen Setup verwende ich Traefik als Reverse Proxy, um Spoolman, das in einem Docker-Container läuft, dem Internet auszusetzen und die SSL-Zertifikate zu verwalten. SSL ist auch erforderlich, um Spoolmans Funktion zum Scannen von QR-Codes Ihrer Spools nutzen zu können.

Die Anforderungen in meinem Setup sind: kein Kennwort erforderlich, wenn Anfragen aus dem lokalen Netzwerk (192.168.1.0/24) kommen; HTTP Basic Authentication erforderlich, wenn Anfragen von außerhalb des Internets kommen.

Auf diese Weise ist für die Integration in mein Klipper-Setup keine Authentifizierung erforderlich, für den Zugriff auf Spoolman aus dem Internet jedoch schon.

Während dies mit Apache HTTPD relativ einfach zu bewerkstelligen wäre, war es mit Traefik etwas knifflig.

Meine Lösung ist, in Traefik zwei http.routers für Spoolman zu definieren. Einer für den Zugriff aus dem internen Netzwerk:

- "traefik.http.routers.spoolman-internal.rule=( Host(`spoolman.example.net`) && ClientIP(`192.168.1.0/24` ))"

und einen für den Zugriff aus dem Internet:

- "traefik.http.routers.spoolman.rule=Host(`spoolman.example.net`) && !ClientIP(`192.168.1.0/24` )"
- "traefik.http.routers.spoolman.entrypoints=websecure"

Beide http.router können dann ihre eigene Traefik-Middlewares-Sektion haben, um Authentifizierung hinzuzufügen oder nicht.

Mein ganzes Spoolman docker-compose.yaml sieht wie folgt aus:

version: '3.8'
services:
  spoolman:
    image: ghcr.io/donkie/spoolman:latest
    restart: unless-stopped
    labels:
       - "traefik.enable=true"
       - "traefik.http.routers.spoolman-internal.rule=( Host(`spoolman.example.net`) && ClientIP(`192.168.1.0/24` ))"
       - "traefik.http.routers.spoolman-internal.entrypoints=websecure"
       - "traefik.http.routers.spoolman.rule=Host(`spoolman.example.net`) && !ClientIP(`192.168.1.0/24` )"
       - "traefik.http.routers.spoolman.entrypoints=websecure"
       - "traefik.http.routers.spoolman.tls=true"
       - "traefik.http.routers.spoolman.priority=2"
       - "traefik.http.routers.spoolman.tls.certresolver=letsencrypt"
       - "traefik.http.routers.spoolman-internal.tls.certresolver=letsencrypt"
       - "traefik.http.routers.spoolman.middlewares=auth-users"
       - "traefik.http.routers.spoolman-internal.tls=true"
       - "traefik.http.routers.spoolman-internal.priority=1"
       - "traefik.http.routers.spoolman.service=svc-spoolman"
       - "traefik.http.routers.spoolman-internal.service=svc-spoolman"
       - "traefik.http.services.svc-spoolman.loadbalancer.server.port=8000"
       - "traefik.http.middlewares.auth-users.basicauth.users=admin:$$2U$$07$$K3XvlqQOC3ScMoRqOIQ50elXe.QByrAvpvmaDp9yj0oaA4LOLiCE6"
    networks:
      - web
    volumes:
      # Mount the host machine's ./data directory into the container's /home/app/.local/share/spoolman directory
      - type: bind
        source: ./data # This is where the data will be stored locally. Could also be set to for example `source: /home/pi/printer_data/spoolman`.
        target: /home/app/.local/share/spoolman # Do NOT change this line
    ports:
      # Map the host machine's port 7912 to the container's port 8000
      - target: 8000
        published: 7912
        protocol: tcp
        mode: host
    environment:
      - TZ=Europe/Stockholm # Optional, defaults to UTC

networks:
  web:
    name: web
    external: true

One thought on “Spoolman behind a Traefik-Proxy in the internal network”

Leave a Reply

Your email address will not be published. Required fields are marked *