11 KiB
Administration API and configuration automation
RustProxy exposes an authenticated administration API on the separate administration listener (normally 127.0.0.1:9090). Open /docs → API after signing in to view the bundled OpenAPI/Swagger schema, including request bodies and available actions. That schema is the endpoint reference; server validation remains authoritative.
Selected API endpoints
The current bundled src/admin/openapi.json declares these operations (among others):
| Method and path | Purpose |
|---|---|
GET /healthz |
Minimal health response, without privileged state. |
GET /api/auth/status |
Whether first-time administrator setup is required. |
POST /api/auth/login · POST /api/auth/logout |
Start/end a browser admin session. |
GET /api/auth/session |
Validate current admin session. |
GET /api/config · PUT /api/config |
Read or replace validated, revisioned configuration. GET also returns read-only storage metadata (SQLite/JSON source and paths). |
POST /api/config/reload |
Revalidate and hot-reload manually changed --config JSON; revision-aware. |
GET/POST /api/api-tokens · DELETE /api/api-tokens/{id} |
List/generate/revoke general RO/RW API tokens (browser-admin-only). |
GET/POST/DELETE /api/prometheus-token |
Inspect/generate/rotate/revoke a standalone Prometheus scrape token (browser-admin-only). |
GET /api/config/{section} · PUT /api/config/{section} |
Read or atomically replace one of 23 supported configuration sections. |
POST /api/config/geoip/update |
Run a GeoIP download/check/reload immediately using already-saved GeoIP settings; does not change revision. |
GET /api/config/history · POST /api/config/history/restore |
Review/restore retained configuration snapshots. |
GET /api/status · GET /api/backends |
Operational status and backend observations. |
GET /api/cache · POST /api/cache/purge · POST /api/cache/invalidate |
Cache observations and authenticated invalidation. |
GET /api/logs · GET /api/live-logs |
Recent and streaming request logs. |
GET /api/file-logs · GET /api/file-logs/query |
Stored-log exploration. |
GET /api/traffic · GET /api/system-info |
Traffic and system observations. |
GET /api/metrics/json · GET /api/metrics/summary |
Full JSON snapshot (includes all Prometheus samples and summary) or compact computed summary only, both pull-only. Monitoring. |
GET /api/docker · POST /api/docker/refresh |
Docker-agent observation and refresh. |
GET /api/certificates · POST /api/certificates/upload |
Certificate inventory/import. |
POST /api/certificates/inspect |
Read DNS SAN coverage from a managed/external public PEM path for the editor; admin browser session only. |
GET /api/acme · POST /api/acme/issue · POST /api/acme/renew |
Managed certificate jobs. |
GET/PUT /api/preferences |
Personal UI settings. |
GET /api/dashboard-presets and named preset operations |
Saved Overview presets. |
GET /docs/openapi.json |
Protected machine-readable API specification. |
Some paths have additional DELETE/PATCH operations, job-status resources, query parameters or restricted actions. Use OpenAPI for the actual fields/methods, not guesses based on a table. GET /metrics here is not a replacement for the separate Prometheus exporter.
Certificate inspection accepts { "cert_file": "filename.pem" } for a managed file or an absolute external path and returns { "cert_file": "...", "covered_hosts": ["example.com"] }. It applies the existing certificate-file trust and size checks and reads no private key. It makes no configuration or permission changes. This POST requires the signed-in administrator's normal Origin, request-marker and CSRF checks; general RO/RW API tokens and certificate-only credentials cannot call it.
Authentication and safe writes
- Ordinary API calls require an administrator browser/session cookie on the admin listener, or a scoped general API Bearer token for explicitly allowlisted API methods/paths. Browser-session writes require the matching Origin,
X-CSRF-TokenandX-RustProxy-Request: 1, in addition to Host validation. Scoped Bearer-token requests are exempt from browser CSRF requirements; the server enforces the token permission, source IP allowlist and HTTPS for non-loopback access instead. - The Swagger API tab uses the signed-in session. Read calls can be executed; mutations require explicit confirmation. It cannot bypass server-side authorization.
- Configuration writes are revisioned (
expected_revision) and rejected if based on a stale save.GET /api/configreturns{revision, config, storage};storageis runtime metadata and must not be copied inside the editableconfigobject or included as a write parameter. PUT and history-restore responses remain{revision, config}. Prefer section updates over replacing the entire document when practical. - Each supported section has the same GET and PUT value shape.
GET /api/config/cachereturns{revision, section: "cache", value: {…}}.PUT /api/config/cacheaccepts{"expected_revision": 12, "value": {…}}, using the entire section value from a fresh GET after modification. The response is the full updated{revision, config}envelope (not a section view). Even changes to different sections must use the latest global revision: concurrent stale writes return 409. This is replacement, not JSON Merge Patch. - Section boundaries:
logginguses{"logging": {…}, "error_log": {…}};responseuses{"server_header": {…}, "diagnostic_headers": {…}, "compression": {…}};global-securityuses a singleGlobalSecurityobject includinguser_agent_blocking. For this section, omittinguser_agent_blockingis an invalid PUT rather than silently clearing the denylist. Independentuser-agent-blockinganderror_logsection endpoints do not exist. The prior logging-onlyPUT /api/config/loggingpayload is no longer accepted: read the full logging section and send the paired value. - The section names use kebab-case (e.g.
not-found-hosts,docker-agents,global-security) even when the matching configuration JSON key is snake_case (not_found_hosts,docker_agents,global_security). GeoIP configuration lives atGET/PUT /api/config/geoip(serialized fromconfig.geoip_updates). After saving,POST /api/config/geoip/updatetriggers a source refresh. The old standalone/api/geoip/updateno longer exists. This action changes loaded database files, not the config revision. A read-only API token cannot execute it; a read/write token can. - Full-document config imports remain backward compatible with older root-level
user_agent_blocking; it is migrated intoglobal_security.user_agent_blockingwhen validated. If both positions contain conflicting policies, the import is rejected. Canonical GET and saved config use the nested field. Per-vhostuser_agent_blockingis unchanged. RO General API tokens may GET sections, RW tokens may PUT sections; the same existing authentication, Host/Origin, revision and audit checks apply. /docs, API schemas, configuration, logs, certificates and most observations are not anonymous. Keep the listener restricted and use HTTPS or a tunnel for remote access.
Available configuration sections
The section name in the URL and its corresponding JSON member in a full configuration are:
Section path (/api/config/…) |
JSON member(s) in config |
|---|---|
listeners |
listeners |
docker-agents |
docker_agents |
http2 |
http2 |
pages |
pages |
cache |
cache |
transform |
transform |
forwarding |
forwarding |
headers |
headers |
prometheus |
prometheus |
geoip |
geoip_updates |
administration |
administration |
tls |
tls |
vhosts |
vhosts |
web-services |
web_services |
php-fpm-profiles |
php_fpm_profiles |
redirects |
redirects |
not-found-hosts |
not_found_hosts |
streams |
streams |
acl-profiles |
acl_profiles |
host-policies |
host_policies |
response |
server_header, diagnostic_headers, compression |
logging |
logging, error_log |
global-security |
global_security, including user_agent_blocking |
Every GET returns a value object or array whose shape can be sent unchanged to the matching PUT. For the three grouped sections the value contains exactly the named members; for the other sections it is the serialized value of the matching configuration member. Saving does not alter unrelated sections.
Complete section-update example
GET /api/config/global-security
{
"revision": 7,
"section": "global-security",
"value": {
"user_agent_blocking": {"enabled": true, "patterns": ["bad-bot"]},
"country_access": {"mode": "off", "countries": []},
"acl": null,
"method_policy": {"mode": "off", "methods": []},
"content_type_policy": {"enabled": false, "blocked": []},
"rate_limit": {"enabled": false, "requests": 100, "window_seconds": 60, "burst": 20},
"security_headers": {"hsts": {"enabled": false, "max_age_seconds": 31536000, "include_subdomains": false, "preload": false}, "nosniff": false, "frame_options": "preserve", "referrer_policy": null, "content_security_policy": null, "permissions_policy": null}
}
}
Use the actual complete value returned from GET as the PUT value after editing it; the example is illustrative, not a substitute for fetching the active defaults. Then send PUT /api/config/global-security with {"expected_revision":7,"value":{...}}. A successful PUT returns the complete new configuration envelope; HTTP 409 requires re-reading the section and applying the intended changes to the newer revision. GET never writes. The UI and API use the same validation and transaction path.
Local CLI alternatives
The included rust-proxy program supports configuration and backup operations without turning browser sessions into automation tokens:
rust-proxy --data-dir /var/lib/rustproxy config get
rust-proxy --data-dir /var/lib/rustproxy config validate config.json
rust-proxy --data-dir /var/lib/rustproxy config apply config.json
rust-proxy --data-dir /var/lib/rustproxy config reload
rust-proxy --data-dir /var/lib/rustproxy backup create --output /private/site.rpb
Run CLI commands as an authorized local operator with the correct private data directory. The admin subcommands provide first setup, password recovery, session revocation and status; tls supports certificate generate/import/deploy/reload. Run rust-proxy --help for exact options.
Restricted Certificate API credentials
Settings → Certificate API can create credentials containing a Key ID + Bearer token with explicit certificate-ID grants. New keys default to reload-only; deploy permission is separate. The clear token is displayed at creation/rotation and is not a general admin API token.
An authorized client sends:
Authorization: Bearer <secret>
X-RustProxy-Certificate-Key: <key-id>
The credential can be used only for allowed certificate reload/deploy operations, not configuration, users, metrics or secret management. Non-loopback use requires the appropriate administration HTTPS security boundary. Rotate broad or legacy credentials. See API access and Certificates.