Files
RustProxy/docs/API.md
T
2026-10-25 17:45:57 +01:00

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-Token and X-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/config returns {revision, config, storage}; storage is runtime metadata and must not be copied inside the editable config object 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/cache returns {revision, section: "cache", value: {…}}. PUT /api/config/cache accepts {"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: logging uses {"logging": {…}, "error_log": {…}}; response uses {"server_header": {…}, "diagnostic_headers": {…}, "compression": {…}}; global-security uses a single GlobalSecurity object including user_agent_blocking. For this section, omitting user_agent_blocking is an invalid PUT rather than silently clearing the denylist. Independent user-agent-blocking and error_log section endpoints do not exist. The prior logging-only PUT /api/config/logging payload 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 at GET/PUT /api/config/geoip (serialized from config.geoip_updates). After saving, POST /api/config/geoip/update triggers a source refresh. The old standalone /api/geoip/update no 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 into global_security.user_agent_blocking when validated. If both positions contain conflicting policies, the import is rejected. Canonical GET and saved config use the nested field. Per-vhost user_agent_blocking is 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.