v0.29.0
This commit is contained in:
1 parent
65e082b9d1
commit
76cb4acef0
72 files changed
+6134
-4709
No files matched your search
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Administration API access - 0.28.2
|
||||
# Administration API access - 0.29.0
|
||||
|
||||
## Sign-in boundary
|
||||
|
||||
|
||||
@@ -128,6 +128,14 @@ safety behavior. RustProxy's static-cookie optimization can ignore Cookie only f
|
||||
configured static file extensions; response `Set-Cookie`, `private`, `no-store` and
|
||||
`Vary: Cookie` still prevent unsafe shared reuse.
|
||||
|
||||
### Per-vhost forced-cache targets
|
||||
|
||||
A vhost can opt into an explicitly unsafe `cache.unsafe_force` list for narrowly selected public request targets. It is intentionally not available as a global cache setting. Each configured target starts with `/`; a target without `?` matches by normalized path prefix, while a target containing `?` matches the original path+query prefix.
|
||||
|
||||
For matching GET/HEAD requests, forced mode may ignore request-side bypasses caused by a query string, Cookie, Authorization, `Cache-Control: no-cache`/`no-store`/`max-age=0`, and `Pragma: no-cache`. Protocol-safety exclusions such as Upgrade, unsupported Range/preconditions and request bodies remain in force. Cookie and Authorization values are added to the cached representation's `Vary` identity in forced mode so different credentials/cookies cannot reuse each other's object.
|
||||
|
||||
Forced mode does **not** override response-side privacy policy. `Set-Cookie`, `Cache-Control: private`, `no-store`, `Vary: *`, partial/trailer/SSE/gRPC responses and the normal size/lifetime validation still prevent storage. Use this only for URLs whose origin semantics are understood; ordinary cache defaults remain safer.
|
||||
|
||||
## Request methods and invalidation
|
||||
|
||||
GET and HEAD participate in lookup. They share one representation identity. On a
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ each Docker host, so the proxy container never needs Docker-socket access. See
|
||||
Build locally with a normal OCI builder:
|
||||
|
||||
```bash
|
||||
docker build -t rustproxy:0.28.2 .
|
||||
docker build -t rustproxy:0.29.0 .
|
||||
```
|
||||
|
||||
Persist `/var/lib/rustproxy`; it contains the SQLite database, certificates and the
|
||||
@@ -22,7 +22,7 @@ docker volume create rustproxy-data
|
||||
docker run --rm -d --name rustproxy \
|
||||
-p 8080:8080 \
|
||||
-v rustproxy-data:/var/lib/rustproxy \
|
||||
rustproxy:0.28.2
|
||||
rustproxy:0.29.0
|
||||
|
||||
docker exec rustproxy rust-proxy admin setup-token
|
||||
```
|
||||
|
||||
@@ -38,7 +38,7 @@ Encoded separators (`%2f`, `%5c`), encoded `%`, dot segments and other ambiguous
|
||||
|
||||
## Actions
|
||||
|
||||
A location can proxy to a backend, serve an existing Web Service, or return a local response.
|
||||
A location can proxy to a backend, serve an existing Web Service, return a local response, or redirect the client to another absolute HTTP(S) URL.
|
||||
|
||||
### Proxy
|
||||
|
||||
@@ -61,7 +61,20 @@ The query string is preserved. Rewrites change only the selected source path; re
|
||||
|
||||
`Return custom response` is the equivalent of a simple Nginx `return`: choose an HTTP status from 200 through 599, a Content-Type and a response body. RustProxy does not open a backend connection for this action. `HEAD`, `204` and `304` responses do not send a body.
|
||||
|
||||
For a redirect, use a 3xx status and add a `Location` response header in the visual header configurator.
|
||||
### Redirect
|
||||
|
||||
`Redirect` is a backend-less action. Choose `301`, `302`, `303`, `307` or `308`, set an absolute `http://` or `https://` target, and optionally preserve the incoming query string. RustProxy validates the target and does not allow capture expansion inside the target scheme/authority.
|
||||
|
||||
For capture-based path rewriting, configure a separate **Redirect rewrite regex**. Captures can be referenced as `$1` or `${name}` in the redirect target path/query. This separation mirrors an Nginx `location` selector followed by a separate `rewrite` expression. For example, the Nginx pattern:
|
||||
|
||||
```nginx
|
||||
location ~* \.(?:tar\.gz|zip?)$ {
|
||||
rewrite ^/(.*)$ https://objectstorage.example.invalid/b/repo/o/$1 permanent;
|
||||
}
|
||||
```
|
||||
|
||||
corresponds to a case-insensitive regex Custom location `\.(?:tar\.gz|zip?)$`, action **Redirect**, status `301`, target `https://objectstorage.example.invalid/b/repo/o/$1`, and redirect rewrite regex `^/(.*)$`. Query preservation is controlled independently.
|
||||
|
||||
|
||||
## Request and response headers
|
||||
|
||||
|
||||
+7
-3
@@ -1,6 +1,6 @@
|
||||
# Stored log explorer
|
||||
|
||||
RustProxy 0.28.2 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
|
||||
RustProxy 0.29.0 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
|
||||
|
||||
## Separation from Live Logs
|
||||
|
||||
@@ -63,9 +63,13 @@ The dashboard no longer exposes the configured-file inventory. The Source select
|
||||
|
||||
The browser still never supplies a filesystem path. The server derives sources from the active configuration and reads only regular files. On Unix it opens with `O_NOFOLLOW`; per-vhost enumeration rejects a symlinked directory and accepts only direct regular `.jsonl` children.
|
||||
|
||||
Logrotate-style gzip rotations are discovered next to configured combined access/error files and inside the configured per-vhost directory. Only regular non-symlink files matching the active filename rotation pattern (for example `access.jsonl.1.gz`) are eligible. The browser still refers to them by server-generated source IDs rather than paths.
|
||||
|
||||
Gzip reading is bounded before and after decompression. A compressed source larger than 8 MiB is not decompressed for a query, decompressed output is capped at 64 MiB, and only the bounded tail is parsed/searched. These limits prevent a gzip rotation from becoming an unbounded memory/decompression workload.
|
||||
|
||||
The reader remains bounded:
|
||||
|
||||
- up to 2 MiB scanned from one source;
|
||||
- up to 2 MiB of retained tail data from one source;
|
||||
- up to 8 MiB across one query;
|
||||
- up to 20,000 lines across a query;
|
||||
- at most 32 sources in an all-source query;
|
||||
@@ -75,4 +79,4 @@ The reader remains bounded:
|
||||
|
||||
If more than 32 sources are eligible, the newest 32 are scanned and the response is marked truncated. File reads run in a blocking worker rather than the async proxy runtime.
|
||||
|
||||
The explorer is diagnostic rather than a retention/indexing system. RustProxy does not add rollover, indexing or compression; use operating-system log rotation for retention.
|
||||
The explorer is diagnostic rather than a retention/indexing system. RustProxy does not create rollovers or compress files itself; use operating-system log rotation for retention. Existing gzip rotations can be read as described above.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
# Installing and updating RustProxy 0.28.2
|
||||
# Installing and updating RustProxy 0.29.0
|
||||
|
||||
The scripts prepare a Linux/systemd installation. This source archive is **not a
|
||||
verified production build**: Rust/Cargo, real CA operations, live systemd startup
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ This is the canonical index for the current project documentation. The authentic
|
||||
- [0.25.1 release audit](V0.25.1_AUDIT.md) - historical Traffic/module-split release scope and compiler-regression guards.
|
||||
- [0.25.0 specification audit](V0.25.0_AUDIT.md) - Web Server foundation point-by-point implementation status.
|
||||
- [0.25.0 pre-production security audit](V0.25.0_SECURITY_PREPROD_AUDIT.md) - threat-oriented source/configuration review, fixes made in-session and mandatory runtime security gates.
|
||||
- [0.29.0 implementation note](V0.29.0_IMPLEMENTATION.md) - canonical host/custom-location redirects, health Host defaults, forced cache and gzip Stored Logs.
|
||||
- [0.28.2 implementation note](V0.28.2_IMPLEMENTATION.md) - external certificate ACL/path hardening and least-privilege Certificate API grants.
|
||||
- [0.28.1 implementation note](V0.28.1_IMPLEMENTATION.md) - external certificate paths, Certbot symlink reloads, backup semantics and certificate-source UX.
|
||||
- [0.28.0 implementation note](V0.28.0_IMPLEMENTATION.md) - manual/hot-reloaded GeoIP, listener status UX, cache Via/narrow invalidation and header-rule layout.
|
||||
@@ -74,7 +75,7 @@ This is the canonical index for the current project documentation. The authentic
|
||||
|
||||
## Historical or version-labelled context
|
||||
|
||||
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.28.2_IMPLEMENTATION.md](V0.28.2_IMPLEMENTATION.md); [V0.28.1_IMPLEMENTATION.md](V0.28.1_IMPLEMENTATION.md) is retained as the prior external-path milestone; [V0.28.0_IMPLEMENTATION.md](V0.28.0_IMPLEMENTATION.md) is retained as the prior GeoIP/listener/cache milestone, and [V0.27.3_IMPLEMENTATION.md](V0.27.3_IMPLEMENTATION.md) is retained as the prior HTTP/3/cache-maintenance milestone, [V0.27.2_IMPLEMENTATION.md](V0.27.2_IMPLEMENTATION.md) is retained as the prior managed-ACME repair, [V0.27.1_IMPLEMENTATION.md](V0.27.1_IMPLEMENTATION.md) as the prior managed-runtime/list-sorting milestone, and older version notes remain historical evidence. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain available for traceability.
|
||||
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.29.0_IMPLEMENTATION.md](V0.29.0_IMPLEMENTATION.md); [V0.28.2_IMPLEMENTATION.md](V0.28.2_IMPLEMENTATION.md) is retained as the prior certificate-hardening milestone; [V0.28.1_IMPLEMENTATION.md](V0.28.1_IMPLEMENTATION.md) is retained as the prior external-path milestone; [V0.28.0_IMPLEMENTATION.md](V0.28.0_IMPLEMENTATION.md) is retained as the prior GeoIP/listener/cache milestone, and [V0.27.3_IMPLEMENTATION.md](V0.27.3_IMPLEMENTATION.md) is retained as the prior HTTP/3/cache-maintenance milestone, [V0.27.2_IMPLEMENTATION.md](V0.27.2_IMPLEMENTATION.md) is retained as the prior managed-ACME repair, [V0.27.1_IMPLEMENTATION.md](V0.27.1_IMPLEMENTATION.md) as the prior managed-runtime/list-sorting milestone, and older version notes remain historical evidence. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain available for traceability.
|
||||
|
||||
Older context documents such as [INTEGRATIONS_040](INTEGRATIONS_040.md), [MANAGEMENT](MANAGEMENT.md), [SECURITY_AUDIT](SECURITY_AUDIT.md), [ACME_RFC2136](ACME_RFC2136.md) and older version audits remain available for traceability but should not override the current functional/technical documents above.
|
||||
|
||||
|
||||
+77
-19
@@ -1,29 +1,87 @@
|
||||
# Verification report - RustProxy 0.28.2
|
||||
# Verification report - RustProxy 0.29.0
|
||||
|
||||
## Scope
|
||||
|
||||
RustProxy 0.28.2 hardens the 0.28.1 external-certificate workflow. Absolute certificate/key paths are validated across the configured and resolved parent chains, the final file is opened with `O_NOFOLLOW`, POSIX ACL read access is supported without requiring an exact chmod value, private keys may not be world-readable, and external certificate/key files may not be group/world-writable. The packaged systemd service explicitly keeps `/etc/letsencrypt` and `/etc/ssl` read-only while normal Unix permissions/ACLs remain authoritative for access.
|
||||
This report records verification of the 0.29.0 release source in the packaging environment. The release adds canonical www/non-www redirects, first-class Custom location redirects, automatic HTTP health-check Host selection, per-vhost forced-cache targets, bounded gzip log reading, and regression coverage for 503 maintenance pages and nested URL query strings. SQLite remains schema 9 and Cold Cache remains format 3.
|
||||
|
||||
Certificate automation is also narrowed. SQLite schema 9 adds per-Key-ID grants: new Certificate API tokens require explicit certificate IDs, are reload-only by default, cannot call the global all-certificate reload endpoint, and require an explicit deploy grant before `POST /api/certificates/deploy` is accepted. Credentials from earlier releases migrate to reload-only wildcard compatibility grants and should be rotated to explicit IDs.
|
||||
## Source and release checks
|
||||
|
||||
The release retains the 0.28.0 GeoIP direct-source/MMDB hot reload, listener protocol badges, cache Via/narrow invalidation, Security-editor layout and ACME runtime reporting. COLD cache format 3 and saved proxy configuration format remain unchanged.
|
||||
The repository release gates are executed with:
|
||||
|
||||
## Verification
|
||||
```bash
|
||||
./dev.sh test
|
||||
./dev.sh check
|
||||
```
|
||||
|
||||
| Check | Result |
|
||||
|---|---|
|
||||
| Source/static contracts | PASS - `tools/checks/check_source.py` |
|
||||
| Documentation/index/link checks | PASS - `tools/checks/docs_check.py` |
|
||||
| Browser-side JavaScript syntax/UI contracts | PASS - `./dev.sh test` pre-Cargo stages |
|
||||
| SQLite schema-9 migration and release smoke | PASS - `tools/checks/release_smoke.py`, including legacy-token grant migration |
|
||||
| Docker Agent Go tests | PASS - `go test ./...` |
|
||||
| Shell/Python/JSON syntax checks | PASS - release/static checks plus explicit shell/JSON validation |
|
||||
| `cargo fmt/check/test` | NOT VERIFIED - Rust/Cargo are not installed in this verification environment; `./dev.sh test` exits 127 only after all pre-Cargo gates pass |
|
||||
| Live Certbot ACL + targeted API reload | NOT VERIFIED - requires a compiled binary and host certificate material |
|
||||
| Live HTTP/2 + HTTP/3 protocol tests | NOT VERIFIED - requires a compiled binary and QUIC-capable runtime |
|
||||
`./dev.sh test` runs the Rust-independent source/module, release-smoke, memory, Web Server, security, dependency, browser-UI, documentation and translation checks before attempting Cargo. The 0.29.0 source checks cover the new configuration/UI/runtime contracts as well as retained release behavior.
|
||||
|
||||
## Security regression coverage
|
||||
Additional syntax checks used for the edited browser assets are:
|
||||
|
||||
The source tests include Certbot-style `live/ -> archive/` symlink refresh behavior, acceptance of ACL-style group-mask bits, rejection of group/world-writable or world-readable private-key modes, and rejection of writable non-sticky parent directories. Administration tests cover targeted certificate-ID grants, denial of global reload for Certificate API tokens, rejection of non-allowlisted certificate IDs and independent token revocation.
|
||||
```bash
|
||||
node --check src/admin/web/vhosts/core.js
|
||||
node --check src/admin/web/vhosts/editor.js
|
||||
node --check src/admin/web/vhosts/render.js
|
||||
```
|
||||
|
||||
See [V0.28.2_IMPLEMENTATION.md](V0.28.2_IMPLEMENTATION.md) for the operator ACL example and migration behavior.
|
||||
## Environment limitation
|
||||
|
||||
Rust/Cargo is not installed or not available on PATH in this packaging environment. Therefore Rust parsing, type checking, linking and execution of `cargo test --locked --all-targets` cannot be claimed here. `./dev.sh test` was executed and all Rust-independent gates printed PASS before the script stopped at the explicit Rust/Cargo guard with exit 127. `./dev.sh check` was also executed and stopped at the same guard with exit 127.
|
||||
|
||||
|
||||
Observed auxiliary checks:
|
||||
|
||||
```text
|
||||
node --check src/admin/web/vhosts/core.js PASS
|
||||
node --check src/admin/web/vhosts/editor.js PASS
|
||||
node --check src/admin/web/vhosts/render.js PASS
|
||||
(cd docker-agent && go test ./...) PASS
|
||||
```
|
||||
|
||||
An attempt to fetch a user-local Rust toolchain was unavailable from this environment, so no compiler result is inferred from the source/static checks.
|
||||
|
||||
A Rust-enabled release host must still run:
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo check --locked --all-targets
|
||||
cargo test --locked --all-targets
|
||||
```
|
||||
|
||||
before promoting the binary package.
|
||||
|
||||
## Functional regressions included in source
|
||||
|
||||
The Rust test source includes coverage for:
|
||||
|
||||
- www/non-www companion routing and canonical redirect behavior;
|
||||
- default and explicitly overridden HTTP health-check Host selection;
|
||||
- Custom location redirects with a separate capture regex and query preservation;
|
||||
- per-vhost forced-cache target matching and retained protocol-safety exclusions;
|
||||
- bounded discovery/read of rotated `.gz` Stored Logs;
|
||||
- a static/maintenance HTML response with HTTP 503;
|
||||
- preservation of a valid nested-URL query string in the upstream URI.
|
||||
|
||||
Literal/encoded backslashes remain intentionally rejected by the ambiguous-routing guard. For the reported curl case, use normal query separators inside a quoted URL rather than `\?`, `\=` or `\&`.
|
||||
|
||||
## Post-release source revision: multi-host vhost and canonical selector
|
||||
|
||||
The vhost editor now selects a canonical hostname from the configured host list, with a legacy first-host fallback. An additional Rust regression test verifies independent `suba.local` and `subb.local` aliases and a selected redirect target; invalid foreign redirect targets are rejected. Compiler/runtime tests remain unverified in this environment.
|
||||
|
||||
## Frontends WWW-routing UX revision
|
||||
|
||||
The editor groups host chips and WWW redirect controls in the same Frontends tab. The legacy select is replaced by accessible paired radio choices showing both `www -> bare` and `bare -> www` for each exact host (also while the feature is off), plus a list of non-redirected aliases and the number of configured names. A `www.` destination can be implicit: routing claims both hosts even if only the bare name was listed in the vhost. Wildcards are not offered as redirect targets. The selected target survives unrelated edits and automatically falls back to a valid hostname when removed; wildcard-only configurations disable the redirect control and show guidance. The persisted fields (`www_redirect` and `www_redirect_target`) are unchanged.
|
||||
|
||||
`node tools/checks/vhost_www_ui_test.mjs` runs the actual WWW-routing editor component in a DOM stand-in and covers its switch, selected-target restore, alias visibility, both redirect directions, implicit `www.` target, wildcard handling, removal fallback, and serialization. Rust source includes a complementary runtime regression for the implicit www routing pair. These checks do not substitute for executing Rust proxy runtime tests.
|
||||
|
||||
## WWW UX correction (source revision)
|
||||
|
||||
The Frontends tab now shows the WWW target choices next to its hostname editor, grouped by domain and available for preview even when the feature is disabled. Both www to bare and bare to www destinations are available. A WWW destination may be implicit (`www.subb.local` with only `subb.local` configured); the runtime claims both hostnames for the selected pair, while a second domain (`suba.local`) remains an independent alias of the same vhost and backend. A Rust regression test covers the implicit WWW direction; static checks and JS syntax tests are described above. Full Rust compiler/runtime verification still requires Cargo.
|
||||
|
||||
### WWW UX packaging verification
|
||||
|
||||
In this source revision, `node tools/checks/www_redirect_ui_test.mjs` and
|
||||
`node tools/checks/vhost_www_ui_test.mjs` both pass their DOM-stand-in selection
|
||||
and synchronization checks. `./dev.sh test` passed all pre-Cargo checks and
|
||||
stopped at the missing Cargo guard with exit 127. Syntax checks for the edited
|
||||
JavaScript and the two language JSON packs also passed. This does not establish
|
||||
Rust compile/test success or end-to-end browser behavior.
|
||||
@@ -0,0 +1,41 @@
|
||||
# RustProxy 0.29.0 implementation note
|
||||
|
||||
RustProxy 0.29.0 adds narrowly scoped redirect, health-check, cache and stored-log controls without changing SQLite schema 9 or Cold Cache format 3. Existing 0.28.2 configuration remains compatible because all new configuration fields are defaulted.
|
||||
|
||||
## Canonical www/non-www redirect
|
||||
|
||||
A vhost can enable `www_redirect`. The canonical exact DNS name is chosen in the UI from `frontend.hosts` and persisted as optional `www_redirect_target`; it defaults to the first hostname for older configurations. RustProxy derives its direct companion (`example.com` <-> `www.example.com`), claims that host on the same listeners and returns `308 Permanent Redirect` to the canonical name while preserving the request path/query. Wildcard/IP first hosts are rejected for this option. If `force_ssl` is also enabled, cleartext companion requests redirect directly to the HTTPS canonical URL.
|
||||
|
||||
Certificate assignment includes both routing names, but certificate validity is not synthesized: operators must use a certificate whose SANs cover the canonical and companion names.
|
||||
|
||||
## Custom location redirects
|
||||
|
||||
Custom locations have a backend-less `redirect` action with status `301`, `302`, `303`, `307` or `308`, an absolute HTTP(S) target, optional redirect rewrite regex and optional query preservation. The rewrite regex is separate from the location match regex, so a configuration equivalent to an Nginx `location` followed by `rewrite ^/(.*)$ .../$1 permanent` can capture the complete request path independently of the location selector.
|
||||
|
||||
Capture expansion is allowed in the target path/query but not in the scheme/authority. This prevents client-controlled captures from turning an approved redirect rule into arbitrary-host redirection.
|
||||
|
||||
## Health-check Host selection
|
||||
|
||||
HTTP backend probes already send an HTTP/1.1 Host header. In 0.29.0 an empty `health_check.host` automatically resolves to the first exact DNS hostname of the vhost. This makes IP-address backends with name-based virtual hosting work without repeating the public hostname in the health settings. An explicitly configured health-check Host remains authoritative; if the vhost has no exact DNS hostname, the existing backend-host fallback remains.
|
||||
|
||||
## Per-vhost forced cache
|
||||
|
||||
`cache.unsafe_force` is available only in a vhost override and is disabled by default. Matching GET/HEAD request targets may bypass request-side query, Cookie, Authorization and client cache-control exclusions. Protocol-safety exclusions remain active. Cookie and Authorization are added to variant identity for forced objects.
|
||||
|
||||
Response policy remains authoritative: responses with `Set-Cookie`, `private`, `no-store`, `Vary: *`, partial framing and the other normal non-cacheable conditions are not stored. This option is intentionally labelled dangerous and must be enabled per vhost with explicit target prefixes; it is not a global switch.
|
||||
|
||||
## Rotated gzip logs
|
||||
|
||||
Stored Logs discovers logrotate-style `.gz` siblings of configured combined access/error logs and `.jsonl.*.gz` rotations in the configured per-vhost directory. Only regular non-symlink files derived from configured locations are eligible. Compressed input and decompressed output are bounded, and only the existing bounded tail is parsed/searched.
|
||||
|
||||
## Local page status and URL-query regression coverage
|
||||
|
||||
The existing static/maintenance page model can serve its HTML body with an explicit status such as `503 Service Unavailable`; 0.29.0 adds regression coverage for that operator workflow.
|
||||
|
||||
Valid nested URL query parameters are preserved by upstream URI construction. Literal or percent-encoded backslashes remain rejected by the ambiguous-path guard. A quoted curl URL must therefore use normal `?`, `=` and `&` separators without backslashes.
|
||||
|
||||
## Verification scope
|
||||
|
||||
The release source includes Rust unit/integration regressions for canonical redirects, custom redirect capture/query behavior, automatic health-check Host selection and explicit override precedence, forced-cache request policy and target matching, gzip Stored Logs, maintenance-page 503 and nested URL query preservation. Rust-independent release/source/documentation checks are also retained. See [TEST_REPORT.md](TEST_REPORT.md) for the verification actually performed in the packaging environment.
|
||||
|
||||
Multiple hostnames on the same vhost (for example `suba.local` and `subb.local`) receive identical proxy behavior without implicit redirects.
|
||||
+7
-3
@@ -59,6 +59,8 @@ listener are required so there is both an ingress to redirect and an HTTPS targe
|
||||
several TLS ports are selected, port 443 is preferred; otherwise the selected TLS target
|
||||
port must be unique.
|
||||
|
||||
`www_redirect` defaults to false. When enabled, `www_redirect_target` selects an exact DNS hostname from `frontend.hosts` as canonical (default: the first hostname for backwards compatibility). RustProxy also claims its direct companion (`example.com` <-> `www.example.com`) on the same listeners and returns `308 Permanent Redirect` from that companion to the first hostname while preserving path/query. Wildcards and IP literals cannot be the canonical hostname for this feature. The companion also participates in vhost certificate assignment, but the selected certificate must still contain both DNS names in its SANs. When `force_ssl` is also enabled, an HTTP companion request redirects directly to the HTTPS canonical URL instead of creating two redirect hops.
|
||||
|
||||
`forward_client_ip` defaults to true. Normal vhosts therefore receive the sanitized
|
||||
`Forwarded`, `X-Forwarded-For` and `X-Real-IP` client identity generated by RustProxy.
|
||||
Set it to false for applications whose own trusted-proxy/bypass logic must see the
|
||||
@@ -260,7 +262,7 @@ affinity to the backend that actually answered.
|
||||
|---|---|---|
|
||||
| `mode` | `tcp` | `off`, `tcp`, `http` |
|
||||
| `path` | `/` | Leading slash, up to 1024 bytes; no authority/fragment |
|
||||
| `host` | null | Optional validated HTTP Host override |
|
||||
| `host` | null | Optional validated HTTP Host override; otherwise the first exact vhost DNS hostname is used |
|
||||
| `interval_ms` | 5000 | 250..300000 |
|
||||
| `timeout_ms` | 2000 | 50..60000; no greater than interval |
|
||||
| `slow_response_ms` | 1500 | 0 disables; otherwise no greater than timeout |
|
||||
@@ -270,7 +272,7 @@ affinity to the backend that actually answered.
|
||||
TCP checks verify that an approved origin address accepts a connection. HTTP checks
|
||||
perform GET on the configured path, without redirects, cookies or authorization.
|
||||
They use HTTP/1.1, including verified TLS when appropriate, and measure time to
|
||||
headers, not the full body. For an h2c-only service, use TCP checks. Slow probes
|
||||
headers, not the full body. When `health_check.host` is empty, RustProxy automatically uses the first exact DNS hostname configured on the vhost so an IP-address backend can still route the probe through its name-based virtual host. If no exact DNS hostname exists, the existing backend-host fallback remains. Set `health_check.host` only when the probe must use a different Host value. For an h2c-only service, use TCP checks. Slow probes
|
||||
count as active failures. Active TCP/HTTP health is independent from `passive_health`.
|
||||
|
||||
`passive_health.enabled` defaults to `false`. With that default, normal user traffic
|
||||
@@ -407,7 +409,7 @@ storage and before downstream compression. Origin `Cache-Control: no-transform`
|
||||
wins and cannot be overridden from the vhost.
|
||||
|
||||
Pages offers a static/maintenance response, a fallback for unassigned paths, and
|
||||
error overrides. Vhosts still retain their configured backend pool; static mode
|
||||
error overrides. The static/maintenance response can set an explicit HTTP status independently of its HTML body, so an operator can serve a maintenance document as `503 Service Unavailable` instead of returning `200`. Vhosts still retain their configured backend pool; static mode
|
||||
avoids forwarding but is not a backend-less static-file server. Host/path ACLs run
|
||||
first. Explicit error-status overrides change presentation, not authorization.
|
||||
Empty/inherit means use the global error policy; to disable one inherited error
|
||||
@@ -420,3 +422,5 @@ to override inheritance. See MANAGEMENT.md for exact precedence.
|
||||
New backends use the backend URL host for the upstream `Host` header by default, matching nginx `proxy_pass` behavior. Enable **Preserve client Host** only when the application intentionally routes on the public hostname. This is especially important for embedded/lighttpd-style administration panels that may close or reject requests carrying an unknown Host. Existing explicit settings are preserved during upgrades.
|
||||
|
||||
When an upstream request fails before an HTTP response is received, access logs include a bounded `upstream_error` field in addition to `upstream_status`.
|
||||
|
||||
Multiple explicit hostnames can belong to a single vhost: `suba.local` and `subb.local` share the same routing, backends and configuration. Only the www/non-www companion of the selected canonical hostname redirects; other aliases continue serving traffic directly.
|
||||
Reference in new issue
Block a user