Using iocaine as a Traefik middleware

Getting started

Because Traefik’s documentation heavily emphasizes containers, in this guide, we’ll combine Traefik’s Docker example, and our own Getting Started with Containers guide. We will, of course, need Docker (or Podman) too.

We’ll start with a compose.yaml, modeled after the Traefik documentation, with Traefik itself, and the “whoami” demo application:

services:
  traefik:
    image: traefik:v3.5
    command:
      - "--api.dashboard=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"

We’re going to need iocaine too, and the Traefik iocaine middleware. We’re going to add the former to our compose.yaml, but lets clone the latter!

# git clone https://git.mstar.dev/mstar/traefik-iocaine-middleware.git \
    plugins-local/src/git.mstar.dev/mstar/traefik-iocaine-middleware

Why into such a directory? Because the plugin is (thankfully) not on GitHub, so the only way to install it is through local mode, and that requires this layout.

A full configuration will be shown at the end of this guide, should you wish to skip ahead and start playing immediately.

Integrating iocaine

First, lets add the iocaine container to our compose file! For the sake of simplicity, I’ll use a simplified version, but feel free to follow the Getting Started with iocaine and containers guide, and copy the service you ended up with.

Here, we’ll add the following block under services:

  iocaine:
    image: git.madhouse-project.org/iocaine/iocaine:latest
    ports:
      - '127.0.0.1:42069:42069'
    environment:
      - RUST_LOG=iocaine=info

This doesn’t do much yet, we have to tell Traefik about it! Lets add two more lines to the traefik service’s commandline: one to enable the middleware, and the other to tell traefik where to find it. The traefik service should look like this after that:

  traefik:
    image: traefik:v3.5
    command:
      - "--api.dashboard=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      # The following two lines are NEW:
      - "--entrypoints.web.http.middlewares=iocaine@docker"
      - "--experimental.localPlugins.iocaine.moduleName=git.mstar.dev/mstar/traefik-iocaine-middleware"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      # The next line is also NEW:
      - ./plugins-local:/plugins-local
      - /var/run/docker.sock:/var/run/docker.sock

Oh, right, yes, we also mount the local plugins-local to /plugins-local, to make the source of the plugin available for traefik! The entrypoints line tells traefik where to find the configuration for the entrypoint: attached to iocaine@docker. Lets adjust our iocaine service, and add a label or two:

  iocaine:
    image: git.madhouse-project.org/iocaine/iocaine:latest
    ports:
      - '127.0.0.1:42069:42069'
    environment:
      - RUST_LOG=iocaine=info
    labels:
      - 'traefik.http.middlewares.iocaine.plugin.iocaine.iocaineHttpUrl=http://iocaine:42069'
      - 'traefik.http.middlewares.iocaine.plugin.iocaine.methods=GET,HEAD'

This tells the middleware the iocaine URL, and makes it filter GET and HEAD request methods only.

Surprisingly, once we docker compose up -d, we’re done:

# curl http://whoami.localhost
Hostname: dc31c07c9b64
IP: 127.0.0.1
IP: ::1
IP: 10.89.2.2
IP: fe80::88a1:78ff:fe16:ef69
RemoteAddr: 10.89.2.4:54760
GET / HTTP/1.1
Host: whoami.localhost
User-Agent: curl/8.14.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.89.2.1
X-Forwarded-Host: whoami.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: d7cf6d6301bb
X-Real-Ip: 10.89.2.1
# curl http://whoami.localhost -A GPTBot
...garbage...

Full configuration

To summarize, this is the final compose.yaml we ended up with:

services:
  iocaine:
    image: git.madhouse-project.org/iocaine/iocaine:latest
    ports:
      - '127.0.0.1:42069:42069'
    environment:
      - RUST_LOG=iocaine=info
    labels:
      - 'traefik.http.middlewares.iocaine.plugin.iocaine.iocaineHttpUrl=http://iocaine:42069'
      - 'traefik.http.middlewares.iocaine.plugin.iocaine.methods=GET,HEAD'

  traefik:
    image: traefik:v3.5
    command:
      - "--api.dashboard=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.middlewares=iocaine@docker"
      - "--experimental.localPlugins.iocaine.moduleName=git.mstar.dev/mstar/traefik-iocaine-middleware"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - ./plugins-local:/plugins-local
      - /var/run/docker.sock:/var/run/docker.sock

  whoami:
    image: traefik/whoami
    labels:
      - "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"