This page is in English — dit artikel is momenteel alleen in het Engels beschikbaar.
Automating Caddy's Admin API from TypeScript
@viaalink/caddy-api-client is a typed TypeScript client for Caddy's Admin API. Build routes with type-safe helpers, keep the admin endpoint on localhost, and fail fast on timeouts and bad input.
TL;DR: @viaalink/caddy-api-client (version 0.10.1) is a TypeScript client for Caddy’s Admin API. You get IDE autocomplete and compile-time checks for route structures, runtime validation with Zod, and a request timeout that is on by default. It does not change Caddy’s security model: the admin endpoint still has to stay private.
Caddy’s Admin API lets you load, inspect, and change a running configuration without restarting the server. That is what makes it useful for automation. It is also powerful: anyone who can reach the endpoint can change the server’s routes.
What the Admin API gives you
Caddy’s admin endpoint listens on localhost:2019 by default. It exposes endpoints such as:
POST /loadto replace the whole configuration/config/...to read and change one part of the configurationPOST /adaptto convert another config format, such as a Caddyfile, to JSON
Raw JSON is easy to get wrong. A misspelled key or a wrong nesting only fails when Caddy receives it, and two automation steps that edit the same part of the config can overwrite each other.
Install
The package was previously published as @accelerated-software-development/caddy-api-client. The old name is deprecated, and its last version (0.10.1) only re-exports the new package. To migrate, change the package name in package.json and in your imports. The subpaths stay the same.
npm install @viaalink/caddy-api-client zodzod is a peer dependency, used for runtime validation.
Usage
The client talks to the admin endpoint over HTTP. The adminUrl option defaults to http://127.0.0.1:2019.
import { CaddyClient, buildServiceRoutes } from "@viaalink/caddy-api-client/caddy";
const client = new CaddyClient({ adminUrl: "http://127.0.0.1:2019" });
const routes = buildServiceRoutes({
host: "api.localhost",
dial: "127.0.0.1:3000",
serviceId: "my-api",
});
await client.addRoutes("https_server", routes);
const current = await client.getRoutes("https_server");
await client.removeRoutesByHost("old-api.localhost");The client has methods for the common operations: getConfig, getRoutes, addRoute, addRoutes, patchRoutes, replaceRouteById, removeRouteById, removeRoutesByHost, applyConfig, adapt, reload, and getVersion. Route builders include buildServiceRoutes, buildHostRoute, buildPathRoute, buildLoadBalancerRoute, and buildSecurityHeadersHandler.
Prefer the builders over hand-written JSON. They produce the route shape Caddy expects and validate their inputs.
Why a typed client helps
A client does not replace Caddy’s model. It makes the correct shape the easy one.
Autocomplete and types. Your editor shows the valid fields and nesting for a route, so you do not have to look them up in the docs.
Safer refactors. When a route definition changes, the compiler points at every place that uses it.
Clear errors. Failures are thrown as typed errors: ValidationError for bad options or input, CaddyApiError for responses from Caddy, NetworkError for connection problems, and TimeoutError when a request takes longer than the timeout. The default timeout is 5000 ms and you can change it in the constructor options.
Narrow edits. Adding or removing one route changes one part of the configuration. Replacing the whole configuration with POST /load has a much larger blast radius, so keep it for cases where you really need it.
Security baseline
Assume the Admin API is sensitive. Caddy’s documentation says the endpoint should not be exposed publicly, and that processes that run untrusted code on the same server should be isolated and the endpoint bound to a permissioned Unix socket.
- Keep the endpoint on localhost. This is the default. Only open it to a network you control, such as a private VLAN or a VPN.
- Use a Unix socket where you can. Caddy supports a socket address such as
unix//run/caddy-admin.sock. The client’sadminUrloption expects an HTTP(S) URL, so check how your setup connects before you rely on a socket. - Turn the endpoint off if you do not need runtime changes. In the Caddyfile global options,
admin offdisables it. Caddy then needs a restart to pick up configuration changes.
The client reduces accidental misuse. It does not change the security model. You still have to protect access to the endpoint.
Best practices
- Prefer narrow changes over replacing the whole configuration. A smaller change has a smaller blast radius.
- Check your Caddy version. The package README lists which Caddy version each release is tested against. Version 0.9.x through 0.10.x target Caddy v2.11.4.
- Validate at the boundaries. The client validates its options and builder inputs, but validate your own input too, for example data that comes from a deployment system.
- Treat reachability as critical. If the proxy is reachable from outside, assume an attacker could rewrite its routes.
Closing
Caddy’s Admin API is a clean way to automate a production web server. It is also easy to misuse. @viaalink/caddy-api-client makes the correct route shapes easier to write and keeps failures visible. Keep the endpoint private and the automation stays safe.
Get started: NPM package (the package page links to the source repository)
Install from npm