Technical

Proxmox as provider: Traefik auto-discovery without an official provider

Proxmox as provider: Traefik auto-discovery without an official provider

Proxmox as provider for Traefik? There’s no official plugin, but you can still get auto-discovery working with a cron job that pulls from the Proxmox API. It’s a bit of a hack, but it works.

Detailed view of a SATA power cable connector with colorful wiring.

Why there’s no official provider

Traefik has providers for Docker, Kubernetes, and a bunch of cloud services. Proxmox isn’t one of them. There’s an open GitHub feature request that’s been sitting around for years with no merged solution. So if you want Traefik to route to your Proxmox VMs and containers automatically, you’re on your own.

The workaround: cron + API

The idea is simple: a script queries the Proxmox API for all running VMs and LXC containers, grabs their IPs and hostnames, and writes a Traefik dynamic configuration file. Then a cron job runs it every minute or so. Traefik watches that file and updates its routes.

Here’s a basic script to get you started. It uses the Proxmox API and outputs a YAML file for Traefik:

#!/bin/bash
# Fetch running VMs and containers from Proxmox API
# Requires jq and curl

API_URL="https://your-proxmox-host:8006/api2/json"
TOKEN="PVEAPIToken=your-token-id=your-secret"
OUTPUT="/etc/traefik/proxmox.yml"

echo "http:" > $OUTPUT
echo "  routers:" >> $OUTPUT

# Get all VMs
curl -sk -H "Authorization: $TOKEN" "$API_URL/cluster/resources?type=vm" | jq -r '.data[] | select(.status=="running") | .name, .networks[0].ip_addresses[0]' | while read -r name; do
  read -r ip
  if [ -n "$ip" ]; then
    echo "    $name:" >> $OUTPUT
    echo "      rule: \"Host(\`$name.local\`)\"" >> $OUTPUT
    echo "      service: $name" >> $OUTPUT
    echo "      entryPoints: [web]" >> $OUTPUT
    echo "  services:" >> $OUTPUT
    echo "    $name:" >> $OUTPUT
    echo "      loadBalancer:" >> $OUTPUT
    echo "        servers:" >> $OUTPUT
    echo "          - url: \"http://$ip:80\"" >> $OUTPUT
  fi
done

You’ll need to adjust the API token and maybe the network field. Some VMs have multiple NICs, so the IP might be in a different spot. Check your API response with curl -sk -H "Authorization: $TOKEN" "$API_URL/cluster/resources?type=vm" | jq to see the structure.

Vibrant close-up of a USB cable against a purple gradient background.

Set up the cron job

Run the script every minute. Add this to crontab:

* * * * * /usr/local/bin/traefik-proxmox.sh

Then tell Traefik to watch the file. In your static config:

providers:
  file:
    filename: /etc/traefik/proxmox.yml
    watch: true

That’s it. New VMs show up within a minute. Deleted ones disappear. It’s not as clean as an official provider, but it’s damn close.

My take

This is a pain to set up, but once it’s running it’s solid. I’d rather have this than manually editing Traefik config every time I spin up a test container. If you’re running a homelab with lots of short-lived VMs, it’s worth the effort. If you only have a handful of services, just write the static config by hand and skip the script.

One thing to watch: the API token needs read access to the cluster. Don’t use the root password. And if you’re on Proxmox 8, the API path is the same, but the token format changed slightly—make sure you’re using the new PVEAPIToken format.

If you’re already dealing with Proxmox quirks, you might also hit the GPU passthrough black screen issue or the memory ballooning not reducing RAM problem. Homelabbing is a series of small fires.

Leave a comment

Comments are reviewed before they appear. Your email is never published.