Features
DockYARP’s runtime behavior, feature by feature. See Configuration for the labels, environment variables, and application settings referenced here.
Discovery
DockYARP watches the Docker daemon and builds its routes from each container’s labels/environment variables, reconciling live as containers start and stop.
- Health-aware: a container failing its Docker health check is excluded, so healthy replicas keep serving.
- Network selection: on multi-network setups,
Docker:PreferredNetworkpicks the backend address;Docker:ProxyNetworksrestricts selection to a network the proxy shares (reachable), andDocker:HostAddressreaches host-network backends (which have no container IP). - IPv6: the edge listens dual-stack by default (IPv6 and IPv4 clients are served — no toggle needed, unlike
nginx-proxy’s opt-in
ENABLE_IPV6). SetDocker:PreferIpv6to forward to a backend’s IPv6 address when it has one (nginx-proxyPREFER_IPV6_NETWORK); a single family is used per backend, so there are no duplicate endpoints. - Filtering:
Docker:ContainerFiltersscopes discovery with Docker-native filters (for example, only containers labelleddockyarp.enable=true).
Routing & load balancing
- Matching: requests route by
Host(and an optional path prefix). An exact host beats a wildcard (*.example.com);DOCKYARP_PRIORITYorders same-host routes (higher wins). - Multiport:
VIRTUAL_HOST_MULTIPORTSmaps host → path → port on a single container. - Path rewrite:
VIRTUAL_DEST=/strips theVIRTUAL_PATHprefix before forwarding. - Regex paths: a
~-prefixedVIRTUAL_PATH(for example~^/(app1|alt1)/) matches by regular expression; a prefix path beats a regex path, andVIRTUAL_DESTdoes not apply to a regex path. - Replicas & policy: containers sharing a
VIRTUAL_HOSTform one cluster;DOCKYARP_LBselects the load-balancing policy —round-robin(default),least-requests,power-of-two-choices,random, orfirst-alphabetical. - Default host & fallback:
Routing:DefaultHostcatches unknown hosts; otherwise an unmatched request getsRouting:DefaultResponseStatusCode(404 by default), or an optional redirect viaRouting:DefaultResponseLocation.
TLS & ACME
DockYARP terminates TLS and can obtain certificates automatically.
- Automatic certificates: a host with
LETSENCRYPT_HOSTis provisioned over ACME (HTTP-01 by default) and renewed before expiry; a host with no certificate gets a self-signed fallback. - Wildcard certificates via DNS-01: set
DOCKYARP_ACME_CHALLENGE=dns-01and a wildcardLETSENCRYPT_HOST(*.example.com) to get a real ACME-issued wildcard certificate — HTTP-01 cannot issue one, DNS-01 is the only way. DockYarp talks RFC 2136 (Dynamic DNS Update) to a self-hosted authoritative DNS server (BIND, PowerDNS, CoreDNS, …); configureTls:DnsUpdateServer/DnsUpdateZone/DnsUpdateTsigKeyName/DnsUpdateTsigKeySecret. - Provided & shared certs: drop PEM/PFX files in the certificate directory;
CERT_NAMEpins a host to a shared SAN/wildcard certificate (not ACME-provisioned). - Per-connection policy: the certificate, TLS version, and ciphers are selected per SNI host — a per-host
SSL_POLICYoverrides the global posture. Presets are the Mozilla ones (Modern/Intermediate/Old) and the classic AWS ELB policy names (clamped to DockYARP’s TLS 1.2 floor, best-effort ciphers). - Mutual TLS: configure a client CA (
Tls:ClientCaCertificatePath) and optionally a revocation list (Tls:ClientCrlPath), then set a per-route requirement withDOCKYARP_CLIENT_CERT.requiredrejects a missing/untrusted/revoked certificate (403, or the handshake itself fails for an untrusted/revoked one);optionalnever rejects or drops the connection on the certificate’s trust outcome — the backend receivesX-SSL-Client-Verify: SUCCESS/FAILED/NONEand decides for itself. A verified (SUCCESS) certificate’s identity is also passed asX-SSL-Client-S-DN(subject) andX-SSL-Client-I-DN(issuer); client-suppliedX-SSL-Client-*headers are always stripped (anti-spoof). - Enforcement:
HTTPS_METHODcontrols HTTP↔HTTPS behavior per host (see Configuration).
Access control
- Basic Auth: protect a route with
DOCKYARP_AUTH_USER/DOCKYARP_AUTH_PASSWORDlabels, or with mounted Apache htpasswd files (Security:HtpasswdDirectory) — a file named<host>protects that host and<host>_<sha1(path)>protects a specific path. bcrypt, apr1, and SHA1 ({SHA}) hashes are verified, and the files are reloaded live. A request is allowed if it matches a label credential or any htpasswd entry. - Internal-only:
NETWORK_ACCESS=internalrestricts a route to the internal client ranges (Security:InternalRanges); other clients get403. - Mutual TLS: require client certificates per route with
DOCKYARP_CLIENT_CERT(see TLS & ACME).
Proxying
- Forwarded headers: proxied requests carry
X-Forwarded-For,X-Forwarded-Proto,X-Forwarded-Host,X-Forwarded-Port,X-Real-IP,X-Forwarded-Ssl(on/off, matching the forwarded scheme), andX-Original-URI(the original path + query), plus the originalHost. Client-suppliedX-Forwarded-*values are trusted and appended by default; setProxy:TrustDownstreamProxy=falseto replace them with the real connection values (X-Original-URIis always the real request URI). - Compression: responses with compressible content types are gzip/brotli-compressed when the client sends
Accept-Encoding(on by default; disable withCompression:Enabled=false). An already-encoded upstream response is never double-compressed. - httpoxy mitigation: a client-supplied
Proxyrequest header is stripped before the request is forwarded to the backend.
Observability
- Metrics:
GET /metricsexposes Prometheus metrics (active route/cluster counts, and more) for scraping. - Access log: one structured entry per handled request. The field catalog is
Method,Scheme,Host,Path,Query,Protocol,RemoteIp,UserAgent,Referer,StatusCode,ElapsedMs. Configure withAccessLog:Enabled,AccessLog:ExcludedPathPrefixes(default/metrics,/api), andAccessLog:Fields(an ordered selection — the structured analog of nginxLOG_FORMAT). Text or JSON, per the logging provider.
Admin API
The admin surface — the JSON API below, the dashboard, and /metrics — is off by default
(AdminApi:Surface: Disabled). Set it to Api (JSON endpoints + /metrics, no dashboard) or ApiAndDashboard
to turn it on; either value requires AdminApi:Host to be set (the app fails to start otherwise), so the
surface is always scoped to a dedicated host, never shadowing a backend’s own paths.
Read-only JSON endpoints for operators, protected by an API key. Set AdminApi:ApiKey and send it in the
X-Api-Key header; without a valid key the endpoints return 401.
| Endpoint | Returns |
|---|---|
GET /api/version | the running build’s version (git-derived) |
GET /api/routes | the active routing configuration (no secrets — Basic Auth is flagged, never shown) |
GET /api/clusters | the active clusters and their endpoints |
GET /api/certs | stored certificates (host + expiry, no private keys) |
GET /api/health | overall status from real signals (discovery connectivity, certificate count, route/cluster counts) |
GET /api/resolve?host=<h>&path=<p> | the effective configuration a request would match (route, transforms, TLS, security, cluster), or 404 |
curl -H "X-Api-Key: $KEY" "http://localhost:8080/api/resolve?host=app.local&path=/api"
Admin dashboard
GET /dashboard renders a light, read-only HTML view of the same data (current routes/clusters, certificate
expiry, overall health) — an at-a-glance macro view, not a replacement for /metrics or the JSON API. It
reads its data server-side and never calls /api/* from the browser, so it carries no application-level
authentication of its own — unlike /api/*, no API key protects it. It only serves when
AdminApi:Surface is ApiAndDashboard; set it to Api instead to keep the JSON API without the dashboard, or
leave Surface at its default (Disabled) to serve neither.
Setting AdminApi:AllowCertificateDownload: true (default false) adds certificate and private-key download
links to the dashboard’s certificate table. This is opt-in for a reason: once enabled, a stored certificate’s
private key becomes downloadable over HTTP, protected only by the same network isolation (AdminApi:Host) as
the rest of the admin surface — no additional login or token is required. Only turn this on when the admin host
genuinely isn’t reachable from a network you don’t trust.
Setting AdminApi:AllowCertificateConversion: true (default false) adds a “Re-encrypt key” action to the
dashboard’s certificate table once Tls:PrivateKeyEncryptionPassphrase is also set (see Configuration →
Tls): it rewrites a host’s stored private key under the current passphrase, covering both
a first-time enable (an existing plain key) and a passphrase rotation. Hosts whose key is not yet under the
current passphrase are flagged with a “needs re-encryption” badge. Note that encrypting the key this way does
not defend against AllowCertificateDownload above — DockYarp decrypts the key itself, automatically, at
startup, to serve TLS, so it only protects against someone with filesystem/volume/backup access.
Setting AdminApi:AllowCertificateRevocation: true (default false) adds a “Revoke” action to the dashboard’s
certificate table: it revokes the certificate via ACME and removes it from the store, so a fresh certificate
(with a fresh private key) is re-provisioned on the next reconcile pass — the intended response to a
compromised private key. Its own independent opt-in, not gated by AllowCertificateConversion: unlike
that flag’s format-only rewrites, revoking takes the host offline (served via the self-signed fallback) until
re-provisioning completes, and makes an irreversible call to the CA. The dashboard asks for confirmation
before submitting.
Static configuration
Point StaticConfig:Path at a JSON file with Routes, Clusters, and per-host Overrides to configure
DockYARP without Docker labels. It merges with discovery (a static route replaces a discovered one for the same
host/path) and is the sole source when Docker:Enabled=false. An Overrides entry injects response headers for
a host — or default for hosts without a specific override:
{
"Clusters": [{ "Id": "app", "Addresses": ["http://app:8080"] }],
"Routes": [{ "Host": "app.local", "Path": "/", "Cluster": "app" }],
"Overrides": [{ "Host": "default", "ResponseHeaders": { "X-Powered-By": "DockYARP" } }]
}
Custom error pages
Set ErrorPages:Directory to a folder of {statusCode}.html files (for example 404.html, 502.html);
DockYARP overlays them onto its own generated error responses.
Graceful shutdown
On stop, DockYARP drains in-flight requests and stops its background workers within
Host:ShutdownTimeoutSeconds (default 30).