A dynamic reverse proxy for Docker containers, built on YARP and .NET
Automatic service discovery from container labels, dynamic routing, automatic TLS (ACME),
security middleware, and an admin API — an nginx-proxy-style experience, in modern .NET.
Warning
This project is built 100% by AI. Every line of code, spec, and document in DockYarp was produced by an AI agent. It is highly experimental, provided as-is with no guarantees, and is not intended for production or any environment that matters to your business. Treat it as a learning/demonstration project — do not run it where an outage, a security flaw, or data loss would have real consequences.
DockYarp watches your Docker containers and turns their labels into live reverse-proxy configuration —
no restarts, no hand-written routes. Start a container with a VIRTUAL_HOST label and it is instantly
routable; request a certificate with LETSENCRYPT_HOST and HTTPS is provisioned automatically.
- 🐳 Docker auto-discovery — routes/clusters from container labels (nginx-proxy compatible): multi-host,
multi-port (
VIRTUAL_HOST_MULTIPORTS), backend scheme (VIRTUAL_PROTO), path rewrite (VIRTUAL_DEST), priority, and health-aware + network-aware selection. - 🔀 Dynamic routing on YARP — host/path matching, clusters, load balancing, health checks, a default (catch-all) host, per-cluster request timeout and per-route body-size limit; reloaded live.
- 🧾 Configuration sources — Docker discovery and a static JSON file, merged with precedence (static wins); works with or without Docker.
- 🔐 TLS & certificates — automatic ACME (acquire/renew), operator-provided PEM/PFX certs with
wildcard-parent SNI selection,
HTTPS_METHOD(redirect/noredirect/nohttp/nohttps) gated on real cert availability, TLS hardening (min version, ciphers, protocols), and mutual TLS (client-cert auth). - 🛡️ Security middleware — HTTPS enforcement, Basic Auth (from labels), per-host HSTS (+preload), client-certificate enforcement, and hardening headers.
- 📊 Admin API & observability — read-only
/api/*endpoints, Prometheus/metrics, and structured per-request access logging. - 🧯 Custom error pages & proxy tuning — configurable error pages and request limits/timeouts.
- 📦 Container-native — minimal, non-root chiseled image; reference Docker Compose stack.
flowchart LR
Containers["Docker containers<br/>(VIRTUAL_HOST, ... labels)"] -->|discovery| Store[("Routing store<br/>DockYarp.Core")]
Static["Static configuration"] --> Store
Store -->|live reload| YARP["YARP reverse proxy"]
Client["Client"] --> Security["Security<br/>HTTPS · Basic Auth · headers"]
Security --> YARP --> Backends[("Backend containers")]
TLS["TLS / ACME<br/>certs · SNI"] -. serves .- YARP
Admin["Admin API · /metrics"] -. reads .- Store
Each concern is a focused project; DockYarp.Core is a dependency-free leaf that everything else builds on.
See docs/ for the details of each capability.
Run the reference stack (DockYarp + a labeled sample service):
docker compose up -d --build
curl -H "Host: whoami.local" http://localhost/ # proxied to the sample service
docker compose down -vExpose your own service by adding labels:
services:
web:
image: my/web
labels:
VIRTUAL_HOST: app.local
VIRTUAL_PORT: "8080"
LETSENCRYPT_HOST: app.local
LETSENCRYPT_EMAIL: admin@example.comDockYarp needs read-only access to the Docker socket (/var/run/docker.sock) to discover containers.
| Label | Description |
|---|---|
VIRTUAL_HOST |
Host(s) the container is exposed on — comma-separated for several (required*). |
VIRTUAL_PORT |
Target port (inferred when a single port is exposed). |
VIRTUAL_PATH / VIRTUAL_DEST |
Path prefix matched, and destination rewrite (strip the prefix). |
VIRTUAL_PROTO |
Backend scheme: http (default) or https. |
VIRTUAL_HOST_MULTIPORTS |
*YAML host → path → { port, proto, dest }; supersedes VIRTUAL_HOST/VIRTUAL_PORT. |
LETSENCRYPT_HOST / LETSENCRYPT_EMAIL |
Request an ACME certificate for the host. |
HTTPS_METHOD |
redirect (default), noredirect, nohttp, nohttps. |
HSTS |
Per-host Strict-Transport-Security value, or off. |
DOCKYARP_LB / DOCKYARP_PRIORITY |
Load-balancing policy and route priority. |
DOCKYARP_AUTH_USER / DOCKYARP_AUTH_PASSWORD / DOCKYARP_AUTH_REALM |
Basic Auth credentials. |
DOCKYARP_CLIENT_CERT |
Mutual-TLS requirement: required, optional, none. |
DOCKYARP_PROXY_TIMEOUT / DOCKYARP_MAX_BODY_SIZE |
Per-cluster request timeout and per-route body-size limit. |
Full reference: docs/labels-reference.md.
Off by default (AdminApi:Surface: Disabled); set it to Api or ApiAndDashboard (requires AdminApi:Host)
to turn it on. Once enabled, protected by an X-Api-Key header (AdminApi:ApiKey):
| Endpoint | Description |
|---|---|
GET /api/routes |
Active routes (sanitized). |
GET /api/clusters |
Active clusters and endpoints. |
GET /api/certs |
Stored certificates (host + expiry, no private keys). |
GET /api/health |
Overall status with route/cluster/certificate counts and discovery status. |
GET /metrics |
Prometheus metrics (unauthenticated). |
Every request is also written to a structured access log (AccessLog:Enabled).
See docs/admin-api.md.
The build is driven by Fallout (a community fork of Nuke); build.ps1 / build.sh bootstrap it anywhere .NET is installed.
./build.ps1 Test # restore, build, and test (Windows)
./build.sh Test # Linux/macOSOr directly with the .NET SDK (.NET 10, pinned by global.json):
dotnet build DockYarp.slnx
dotnet test DockYarp.slnx./build.ps1 DockerImage # build the chiseled image
docker login <registry> # authenticate first
./build.ps1 DockerPublish --registry registry.example.com --image-repository team/dockyarp --image-tag 1.2.3See docs/deployment.md.
src/
DockYarp.Core/ # models, interfaces, stores (leaf)
DockYarp.Docker/ # Docker discovery + label mapping
DockYarp.Tls/ # ACME + certificates
DockYarp.Security/ # HTTPS enforcement, auth, headers
DockYarp.AdminApi/ # admin/observability endpoints
DockYarp.App/ # ASP.NET host: YARP, DI, pipeline
tests/ # one *.Tests project per src project (NUnit)
build/ # Fallout build project
docs/ # architecture & capability documentation
openspec/ # spec-driven development (specs + changes)
📖 The full documentation site is published at gcelet.github.io/DockYARP. The in-repo capability docs below go deeper on each concern:
| Topic | Document |
|---|---|
| Architecture & nginx-proxy parity | architecture.md |
| Routing model | routing-model.md |
| Docker discovery | docker-discovery.md |
| YARP integration | yarp-integration.md |
| Security middleware | security-middleware.md |
| TLS / ACME | tls-acme.md |
| Admin API & observability | admin-api.md |
| Deployment | deployment.md |
DockYarp is developed spec-first with OpenSpec: every change
starts as a proposal under openspec/ and its specs are archived once implemented. Coding
conventions (modern .NET, strict analyzers, Central Package Management) live in AGENTS.md,
the source of truth for both humans and AI assistants.
Licensed under the MIT License — see LICENSE.