This commit is contained in:
Mateusz Gruszczyński committed 2026-10-04 09:29:10 +02:00
1 parent 2e4aa4df4d
commit 87e571c170
106 files changed
+17952 -6185

No files matched your search

+651 -3
View File
@@ -2,7 +2,7 @@
"openapi": "3.0.3",
"info": {
"title": "RustProxy Administration API",
"version": "0.24.10",
"version": "0.25.0",
"description": "Administration API for the active panel origin. Sign in through the panel; the same-origin HttpOnly cookie authenticates all private operations. Mutations also require the exact Origin, X-RustProxy-Request: 1 and a session-bound X-CSRF-Token. Loopback HTTP is the default; Settings can enable HTTPS before using a non-loopback administration bind. This document contains no live configuration or credentials. Object schemas marked extensible are summaries: full configuration validation is authoritative in Rust."
},
"servers": [
@@ -361,6 +361,9 @@
}
},
"description": "Local response returned by RustProxy without opening a backend connection."
},
"source": {
"$ref": "#/components/schemas/Source"
}
},
"additionalProperties": false,
@@ -509,13 +512,15 @@
"type": "boolean",
"default": false,
"description": "RFC 8441 WebSocket Extended CONNECT over HTTP/2. Independent opt-in alongside classic HTTP/1.1 Upgrade; requires WebSocket support and an H2-capable selected listener."
},
"source": {
"$ref": "#/components/schemas/Source"
}
},
"additionalProperties": true,
"required": [
"id",
"frontend",
"backends"
"frontend"
]
},
"Config": {
@@ -665,6 +670,16 @@
"format": {
"type": "object",
"additionalProperties": true
},
"capture_user_agent": {
"type": "boolean",
"default": true,
"description": "Capture a bounded User-Agent string in access logs and traffic analytics."
},
"capture_country": {
"type": "boolean",
"default": false,
"description": "Resolve country from GeoIP for access logs and traffic analytics. Disabled by default to avoid per-request GeoIP work unless country policy/rate-limit already requires it."
}
}
},
@@ -717,6 +732,13 @@
}
},
"description": "Optional asynchronous ERROR-only file sink. Rotation and retention are handled externally by logrotate."
},
"web_services": {
"type": "array",
"maxItems": 128,
"items": {
"$ref": "#/components/schemas/WebService"
}
}
},
"additionalProperties": true
@@ -1605,6 +1627,25 @@
"minimum": 1,
"maximum": 64,
"default": 4
},
"hot_auto_trim_enabled": {
"type": "boolean",
"default": true,
"description": "When HOT exceeds the configured target, periodically remove only sufficiently idle objects in bounded passes."
},
"hot_auto_trim_after_seconds": {
"type": "integer",
"minimum": 5,
"maximum": 86400,
"default": 300,
"description": "Minimum idle age before an object is eligible for automatic HOT trimming."
},
"hot_auto_trim_target_percent": {
"type": "integer",
"minimum": 10,
"maximum": 95,
"default": 80,
"description": "HOT usage waterline targeted by automatic idle trimming."
}
},
"additionalProperties": false
@@ -4057,6 +4098,530 @@
"http3_new_handshakes",
"administration_restart_required"
]
},
"Source": {
"oneOf": [
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"reverse_proxy"
]
}
},
"required": [
"type"
]
},
{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string",
"enum": [
"web_server"
]
},
"web_service_id": {
"type": "string",
"description": "ID of a reusable Web Service from config.web_services."
}
},
"required": [
"type",
"web_service_id"
]
}
],
"description": "Request source. Missing in older configuration documents is treated as Reverse Proxy."
},
"WebService": {
"type": "object",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"maxLength": 64
},
"name": {
"type": "string",
"maxLength": 96
},
"document_root": {
"type": "string",
"description": "Absolute local filesystem directory forming the static-file access boundary."
},
"index": {
"type": "array",
"maxItems": 16,
"items": {
"type": "string",
"maxLength": 128
},
"description": "Optional ordered index file names. An empty list skips index lookup; directory listing/error behavior applies directly."
},
"directory_listing": {
"type": "boolean",
"default": false
},
"mime_types": {
"type": "object",
"maxProperties": 64,
"additionalProperties": {
"type": "string",
"maxLength": 256
},
"description": "Optional file-extension to Content-Type overrides. Extensions are stored without a leading dot."
},
"default_mime_type": {
"type": "string",
"maxLength": 256,
"default": "application/octet-stream",
"description": "Fallback Content-Type for extensions not covered by an override or RustProxy built-ins."
},
"cache_control": {
"type": "string",
"nullable": true,
"maxLength": 1024,
"description": "Optional default Cache-Control header for files served by this Web Service. Vhost/location response-header rules remain authoritative and may override it."
},
"cache_rules": {
"type": "array",
"maxItems": 64,
"default": [],
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"matcher",
"cache_control"
],
"properties": {
"matcher": {
"type": "string",
"description": "ext:<extension> or mime:<prefix>"
},
"cache_control": {
"type": "string",
"maxLength": 1024
}
}
},
"description": "Ordered per-extension/per-MIME Cache-Control rules evaluated before cache_control."
},
"response_headers": {
"type": "object",
"maxProperties": 32,
"default": {},
"additionalProperties": {
"type": "string",
"maxLength": 8192
},
"description": "Fixed Web Service response headers. Framing/transport headers are rejected; vhost/location response rules run later."
},
"try_files": {
"type": "array",
"maxItems": 16,
"default": [],
"items": {
"type": "string",
"maxLength": 512
},
"description": "Ordered nginx-style file candidates. Supports $uri, $query_string and a final =status."
},
"rewrites": {
"type": "array",
"maxItems": 32,
"default": [],
"items": {
"type": "object",
"additionalProperties": false,
"required": [
"pattern",
"replacement"
],
"properties": {
"pattern": {
"type": "string",
"maxLength": 512
},
"replacement": {
"type": "string",
"maxLength": 1024
},
"status": {
"type": "integer",
"nullable": true,
"enum": [
301,
302,
307,
308
]
}
}
},
"description": "Regex internal rewrites or explicit redirects evaluated before try_files."
},
"precompressed": {
"type": "object",
"additionalProperties": false,
"default": {
"enabled": false,
"brotli": true,
"gzip": true
},
"properties": {
"enabled": {
"type": "boolean",
"default": false
},
"brotli": {
"type": "boolean",
"default": true
},
"gzip": {
"type": "boolean",
"default": true
}
}
},
"download_extensions": {
"type": "array",
"maxItems": 64,
"default": [],
"items": {
"type": "string",
"maxLength": 32
},
"description": "Extensions served with Content-Disposition: attachment."
},
"symlink_policy": {
"type": "string",
"enum": [
"deny",
"inside_root"
],
"default": "deny",
"description": "deny is portable/default. inside_root is a Linux-only opt-in and cannot currently be combined with PHP-FPM."
},
"php": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"default": false
},
"extensions": {
"type": "array",
"maxItems": 16,
"default": [
"php"
],
"items": {
"type": "string",
"maxLength": 32
}
},
"endpoint": {
"type": "string",
"description": "unix:/path or loopback tcp:literal-IP:port, for example tcp:127.0.0.1:9000 or tcp:[::1]:9000"
},
"connect_timeout_ms": {
"type": "integer",
"format": "uint64",
"minimum": 50,
"maximum": 60000,
"default": 1000
},
"request_timeout_ms": {
"type": "integer",
"format": "uint64",
"minimum": 100,
"maximum": 3600000,
"default": 30000
},
"max_concurrent_requests": {
"type": "integer",
"minimum": 1,
"maximum": 4096,
"default": 64
},
"pass_authorization": {
"type": "boolean",
"default": true,
"description": "Forward inbound Authorization as HTTP_AUTHORIZATION to PHP-FPM."
},
"max_request_body_bytes": {
"type": "integer",
"format": "uint64",
"minimum": 0,
"maximum": 8589934592,
"default": 0,
"description": "RustProxy-side streaming PHP request body limit. 0 disables this additional limit."
},
"max_response_header_bytes": {
"type": "integer",
"minimum": 4096,
"maximum": 1048576,
"default": 65536
},
"stderr_log_bytes": {
"type": "integer",
"minimum": 0,
"maximum": 65536,
"default": 4096,
"description": "Maximum PHP-FPM stderr bytes retained per request for diagnostics."
},
"custom_params": {
"type": "object",
"maxProperties": 64,
"default": {},
"additionalProperties": {
"type": "string",
"maxLength": 8192
},
"description": "Trusted static FastCGI NAME=value parameters. Core CGI, HTTP_* and PHP control names are reserved."
},
"php_values": {
"type": "object",
"maxProperties": 64,
"default": {},
"additionalProperties": {
"type": "string",
"maxLength": 8192
},
"description": "Trusted php.ini directive/value overrides combined into the FastCGI PHP_VALUE parameter. PHP_ADMIN_VALUE is not exposed."
}
},
"description": "Optional bounded direct FastCGI connection to a PHP-FPM pool."
},
"htaccess": {
"type": "object",
"additionalProperties": false,
"default": {
"enabled": false,
"filename": ".htaccess",
"scan_subdirectories": true,
"strict": false
},
"properties": {
"enabled": {
"type": "boolean",
"default": false,
"description": "Compile the bounded RustProxy .htaccess compatibility subset for this Web Service."
},
"filename": {
"type": "string",
"maxLength": 64,
"default": ".htaccess",
"description": "Plain configuration file name searched from the document root."
},
"scan_subdirectories": {
"type": "boolean",
"default": true,
"description": "Compile matching files in subdirectories, bounded to depth 16 and 128 files."
},
"strict": {
"type": "boolean",
"default": false,
"description": "Reject Apply when an unsupported directive is found instead of logging and ignoring it."
}
},
"description": "Migration-oriented Apache .htaccess subset compiled at Web Service apply time; never parsed per request."
},
"hardening": {
"type": "object",
"additionalProperties": false,
"default": {
"block_common_attacks": false,
"strip_unnecessary_headers": false
},
"properties": {
"block_common_attacks": {
"type": "boolean",
"default": false,
"description": "Reject high-confidence exploit probes, sensitive dot/control/backup paths and unsafe TRACE/CONNECT/TRACK methods for this Web Service."
},
"strip_unnecessary_headers": {
"type": "boolean",
"default": false,
"description": "Remove common implementation/fingerprint response headers such as Server and X-Powered-By after Web Service/.htaccess processing."
}
},
"description": "Optional Web Service hardening. This is a bounded deterministic compatibility/security layer, not a generic WAF."
}
},
"required": [
"id",
"name",
"document_root"
]
},
"TrafficTopEntry": {
"type": "object",
"additionalProperties": false,
"required": [
"value",
"count"
],
"properties": {
"value": {
"type": "string"
},
"count": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"TrafficCounters": {
"type": "object",
"additionalProperties": false,
"properties": {
"requests": {
"type": "integer",
"format": "int64"
},
"errors": {
"type": "integer",
"format": "int64"
},
"duration_ms": {
"type": "integer",
"format": "int64"
},
"request_bytes": {
"type": "integer",
"format": "int64"
},
"response_bytes": {
"type": "integer",
"format": "int64"
},
"mean_duration_ms": {
"type": "number",
"format": "double",
"nullable": true
},
"countries": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"user_agents": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"client_ips": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"methods": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"statuses": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"routes": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"paths": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
},
"cache": {
"type": "array",
"items": {
"$ref": "#/components/schemas/TrafficTopEntry"
}
}
}
},
"TrafficAnalytics": {
"type": "object",
"additionalProperties": false,
"properties": {
"scope": {
"type": "string"
},
"approximate_top_lists": {
"type": "boolean"
},
"queue_capacity": {
"type": "integer"
},
"queue_dropped": {
"type": "integer",
"format": "int64"
},
"data": {
"$ref": "#/components/schemas/TrafficCounters"
}
}
},
"TrafficStatus": {
"type": "object",
"additionalProperties": false,
"properties": {
"scope": {
"type": "string"
},
"since": {
"type": "string",
"enum": [
"process_start"
]
},
"settings": {
"type": "object",
"additionalProperties": false,
"properties": {
"capture_user_agent": {
"type": "boolean"
},
"capture_country": {
"type": "boolean"
}
}
},
"geoip": {
"type": "object",
"additionalProperties": true
},
"analytics": {
"$ref": "#/components/schemas/TrafficAnalytics"
},
"vhosts": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
}
}
}
}
},
@@ -8371,6 +8936,89 @@
}
]
}
},
"/api/traffic": {
"get": {
"summary": "Bounded per-vhost traffic analytics",
"tags": [
"Traffic"
],
"operationId": "get_api_traffic",
"parameters": [
{
"name": "vhost",
"in": "query",
"required": false,
"description": "Configured vhost ID or * for all vhosts.",
"schema": {
"type": "string",
"default": "*"
}
}
],
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TrafficStatus"
}
}
}
},
"401": {
"description": "Authentication required or revoked",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"description": "Host, origin or CSRF validation failed",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Unknown vhost scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"description": "Bounded worker/session/rate limit",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"503": {
"description": "Control-plane storage/worker unavailable",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}
}
}
}