Skip to main content

Traefik ingress / reverse proxy

v0.1.24

Read-only visibility into a Traefik (v2/v3) edge router over its HTTP API: the overview, entrypoints, and the full HTTP/TCP/UDP router + service + middleware inventory (each carrying its status and error list, so you can see which router is broken), a compact per-service health summary, plus a per-host readiness check that joins the router and service views into one cutover-preflight verdict, the raw dynamic-config dump, version, liveness ping, and Prometheus metrics. ACME/Let's Encrypt certificate state is read from the on-disk acme.json (no API exposes it), and access-log 4xx/5xx tails mirror the nginx pack. Default API at http://127.0.0.1:8080 (api.insecure mode); override via TRAEFIK_URL.

16 allowed by default 2 need approval by default
Pack ID
traefik
Vendor
emisar
OS
linux
Actions
18
Required binaries. Install these on the host before relying on the pack — an action that calls a missing one fails at run time.
curl jq openssl

Install

emisar pack install fetches this pack, re-validates it, and verifies its content hash against the --hash below — the exact bytes this page was rendered against, so a tampered copy is rejected — before copying it into the runner's packs dir. The command reloads a running daemon itself; no manual restart.

on the runner host
sudo emisar pack install traefik --hash sha256:4f98115c8c750aea8e7473d7ae9732112c6b8e629f60b980e1947303046720c4

Setup

The API actions call the Traefik HTTP API at $TRAEFIK_URL via curl on the runner host. The OSS API is read-only (GET-only) by design. ACME cert state and access logs are read from local files, not the API.

Environment

Set these on the runner host, then add each name to execution.inherit_env so the value reaches the action.

  • TRAEFIK_URL default http://127.0.0.1:8080

    Base URL of the Traefik API entrypoint — scheme, host, port. In api.insecure mode this is the dashboard entrypoint on :8080; in production it is whatever entrypoint your api@internal router binds.

  • TRAEFIK_PING_URL

    Base URL of the entrypoint that serves /ping. Defaults to TRAEFIK_URL ; set it when liveness is deliberately separated from the API.

  • TRAEFIK_BASICAUTH

    Optional "user:password" for a production API behind a basicAuth middleware. Base64-encoded and sent as an Authorization header over curl stdin, so it never appears in the process arguments or audit log.

  • TRAEFIK_INSECURE

    Set to "true" to skip TLS verification when the API is served over https with a self-signed certificate.

  • TRAEFIK_ACCESS_LOG default /var/log/traefik/access.log

    Where this host's Traefik access log lives, for the log_grep_* actions. Set it when the log is outside /var/log/traefik — the actions' own log_path argument is deliberately contained to that directory, so this is how the host administrator, rather than a caller, declares a non-standard location.

Host access

Run these commands yourself on the runner host. Emisar shows and copies setup recipes; it never runs them.

Read Traefik's mode-0600 ACME storage and protected access log.

traefik.acme_domainstraefik.acme_cert_expirytraefik.log_grep_4xxtraefik.log_grep_5xx

Run the Emisar service as root

Grant access
sudo install -d -m 0755 /etc/systemd/system/emisar.service.d
printf '%s\n' '[Service]' 'User=root' 'Group=root' | sudo tee /etc/systemd/system/emisar.service.d/10-traefik-host-access.conf >/dev/null
sudo systemctl daemon-reload
sudo systemctl restart emisar
Verify access
test "$(systemctl show emisar --property=User --value)" = root

Impact: Every Emisar action on this runner executes as root. The ACME file contains private keys and account material even though these actions project only certificate metadata.

Notes

  • Any of TRAEFIK_URL / TRAEFIK_PING_URL / TRAEFIK_BASICAUTH / TRAEFIK_INSECURE you set must also be allowlisted in the runner's execution.inherit_env — the action env is scrubbed to PATH/LANG/LC_ALL/TERM by default, so an env present on the host but not allowlisted is silently dropped (the action falls back to its local default or fails auth).
  • Enable the API to use this pack: --api=true (production, behind a router + auth) or --api.insecure=true (exposes it unauthenticated on the :8080 traefik entrypoint — dev only).
  • Every API action is a read-only GET. The OSS Traefik API has no write endpoints; config changes only happen through providers (file/docker/k8s), never the API.
  • Per-router health: each router/service object carries status (enabled | warning | disabled) and an error[] list. Filter for status != enabled to find broken routing. Services also expose serverStatus (per-backend UP/DOWN).
  • ACME certificate material lives only in the acme.json storage file, never the API.
  • /ping defaults to TRAEFIK_URL but is often moved to a dedicated entrypoint; set TRAEFIK_PING_URL without disturbing the API actions.
  • Logs outside /var/log/traefik : set TRAEFIK_ACCESS_LOG (and allowlist it in the runner's execution.inherit_env ). The log_path argument stays contained to /var/log/traefik because a caller — including an LLM — supplies it; the environment is host-administrator state, and anyone who can set it can already read the file. If Traefik logs to stdout instead (no accessLog.filePath), no file exists to read at any path: query whichever store collects it, e.g. the victorialogs pack. For unrestricted /var/log access, install linux-core, whose name says so.

Verify it works

Runs traefik.version, a low-risk read that confirms the pack can reach its target. Run it on the host once the pack is installed; pack install runs it for you.

on the runner host
sudo emisar pack verify traefik

Install and configure a pack walks through the whole sequence on a host.

Actions 18 total

View on GitHub
  • traefik.acme_cert_expiry exec low Low — read-only or trivially reversible

    ACME certificate expiry (from acme.json)

    Show each ACME/Let's Encrypt certificate in acme.json with its domain and notAfter expiry date. Decodes only the public certificate (base64 PEM) through openssl — never touches the private key. Traefik auto-renews 30 days out, so anything closer than that which is NOT renewing is the thing to investigate. Read-only.

    View source on GitHub
  • traefik.acme_domains exec low Low — read-only or trivially reversible

    ACME certificate domains (from acme.json)

    List the domains (CN + SANs) Traefik holds ACME/Let's Encrypt certificates for, read from the on-disk acme.json storage (no API exposes cert state). Reads only the domain fields — never the certificate or private-key material. Use to confirm a hostname actually has an issued cert.

    View source on GitHub
  • traefik.entrypoints script low Low — read-only or trivially reversible

    GET /api/entrypoints

    List all configured entrypoints — name, listen address/port, and transport settings (timeouts, HTTP/2, TLS defaults). Use to confirm the front door is listening where you expect (web :80, websecure :443, etc.).

    View source on GitHub
  • traefik.http_host_readiness script low Low — read-only or trivially reversible

    Check whether a public host is live behind Traefik

    Check a single public host's end-to-end readiness through Traefik — the cutover preflight read. Joins /api/http/routers and /api/http/services into ONE compact verdict: is there an enabled router matching Host(`<host>`), a healthy service behind it, and at least one UP backend? Returns "host", "ready" (true only when nothing is wrong), the matched router and resolved service (name/provider/status/errors), backend counts (up/down/total) with the DOWN backend URLs, and a "failures" list of operator-readable reasons: missing_router, router_not_enabled, router_errors, missing_service, service_not_enabled, service_errors, no_up_backends, backend_down. Use this before a DNS/origin cutover instead of the raw 4 MiB inventory dumps.

    View source on GitHub
  • traefik.http_middlewares script high High — service-affecting

    GET /api/http/middlewares

    List every HTTP middleware (auth, rate-limit, headers, redirects, retries, circuit-breaker, etc.) with its config, status, and error[]. Use to confirm a middleware is configured as expected and not in error. A middleware is where the edge's auth material lives — basicAuth / digestAuth user hashes, injected upstream auth headers, forwardAuth targets — and the operator names those fields, so the runner's redaction is a fail-closed backstop, not a guarantee: it is pattern-bound and can miss a bespoke secret whose name and value match no rule.

    View source on GitHub
  • traefik.http_routers script low Low — read-only or trivially reversible

    GET /api/http/routers

    List every HTTP router with its rule, entrypoints, service, middlewares, TLS config, and — critically — its status ("enabled" | "warning" | "disabled") and error[] list. To find broken routing, look for any router whose status is not "enabled" and read its error[]. Names are "<name>@<provider>" (e.g. my-router@docker).

    View source on GitHub
  • traefik.http_services script low Low — read-only or trivially reversible

    GET /api/http/services

    List every HTTP service with its load-balancer config, status, error[], and serverStatus — a per-backend map of URL to "UP"/"DOWN". This is the "which upstream is down?" read: a service with a DOWN server (or a non-"enabled" status) is failing health checks.

    View source on GitHub
  • traefik.http_services_summary script low Low — read-only or trivially reversible

    List HTTP services, compact health summary

    List every HTTP service as a compact, name-sorted health summary — the preflight-sized view of /api/http/services without its multi-megabyte load-balancer config. One row per service: name, provider, status, error_count + errors, backend counts (up/down/total), and the URLs of only the DOWN backends. Set only_unhealthy=true to return just the services that need attention (not "enabled", carrying errors, a DOWN backend, or a load-balancer with no UP backend). Use traefik.http_services for the full raw load-balancer config of a single service.

    View source on GitHub
  • traefik.log_grep_4xx exec medium Medium — changes state, easily reversible

    Recent 4xx responses from access log

    Grep the Traefik access log for 4xx responses and tail the most recent. Matches both the JSON format (DownstreamStatus field) and the default CLF format (status code after the request line). Needs an access log on disk, which Traefik writes only when accessLog.filePath is set; when it logs to stdout instead, query whichever log store collects it. Read-only.

    View source on GitHub
  • traefik.log_grep_5xx exec medium Medium — changes state, easily reversible

    Recent 5xx responses from access log

    Grep the Traefik access log for 5xx responses and tail the most recent — the front-door view of backend failures. Matches both the JSON format (DownstreamStatus field) and the default CLF format. Needs an access log on disk, which Traefik writes only when accessLog.filePath is set; when it logs to stdout instead, query whichever log store collects it. Read-only.

    View source on GitHub
  • traefik.metrics script low Low — read-only or trivially reversible

    GET /metrics

    Show Prometheus metrics in text exposition format (requires --metrics.prometheus=true): per-entrypoint/router/service request counts, durations, open connections, and TLS cert expiry gauges. Served on the traefik entrypoint (:8080) by default unless metrics.prometheus.entryPoint moves it.

    View source on GitHub
  • traefik.overview script low Low — read-only or trivially reversible

    GET /api/overview

    Show dashboard summary — counts of HTTP/TCP/UDP routers, services, and middlewares by state (enabled/warning/errored), enabled providers, and which features (metrics, tracing) are on. The fastest "is anything broken?" read before drilling into the per-router inventory.

    View source on GitHub
  • traefik.ping script low Low — read-only or trivially reversible

    GET /ping

    Check liveness. Returns 200 with body "OK" when healthy, or the configured terminating status (default 503) during graceful shutdown. Requires --ping=true; served on the ping entrypoint (the traefik entrypoint / :8080 by default). Set TRAEFIK_PING_URL when that entrypoint differs from the API.

    View source on GitHub
  • traefik.rawdata script high High — service-affecting

    GET /api/rawdata

    Dump the complete dynamic configuration as Traefik currently sees it — all routers, services, and middlewares across HTTP/TCP/UDP, each with its errors, plus the "usedBy" dependency graph tying routers to services and middlewares. The single most complete read for "what is the actual live config and what depends on what?". Larger than the per-kind endpoints. Middleware config is operator-authored and can carry secrets (basicAuth / digestAuth user hashes, injected upstream auth headers, forwardAuth targets). The runner's redaction is a fail-closed backstop, not a guarantee — it is pattern-bound and can miss a bespoke secret whose name and value match no rule.

    View source on GitHub
  • traefik.tcp_routers script low Low — read-only or trivially reversible

    GET /api/tcp/routers

    List every TCP router with its rule (HostSNI/...), entrypoints, service, TLS passthrough config, status, and error[]. Use for TCP/SNI routing (databases, message brokers, raw TLS) the same way http_routers covers HTTP.

    View source on GitHub
  • traefik.tcp_services script low Low — read-only or trivially reversible

    GET /api/tcp/services

    List every TCP service with its load-balancer/weighted config, status, and error[]. The TCP counterpart to http_services.

    View source on GitHub
  • traefik.udp_routers script low Low — read-only or trivially reversible

    GET /api/udp/routers

    List every UDP router (and its service binding) with status and error[]. Use for UDP entrypoints (DNS, QUIC, syslog) routing visibility. Pair with /api/udp/services via rawdata if you need the service side.

    View source on GitHub
  • traefik.version script low Low — read-only or trivially reversible

    GET /api/version

    Show Traefik version, codename, and build/start date. Use to confirm which release is running (v2 vs v3 behaviour) and that the API answers.

    View source on GitHub