v0.3
This commit is contained in:
1 parent
28e39f7ce4
commit
b57beb83c7
34 files changed
+1037
-314
No files matched your search
+2
-2
@@ -12,7 +12,7 @@ The current bundled `src/admin/openapi.json` declares these operations (among ot
|
||||
| `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 /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). |
|
||||
@@ -36,7 +36,7 @@ Some paths have additional DELETE/PATCH operations, job-status resources, query
|
||||
|
||||
- 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. Logging in also provides CSRF context. Writes require correct Host/Origin, `X-CSRF-Token` and `X-RustProxy-Request: 1` as enforced by the server.
|
||||
- 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. Prefer section updates over replacing the entire document when practical.
|
||||
- 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.
|
||||
- `/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.
|
||||
|
||||
## Local CLI alternatives
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
|
||||
Most settings are managed in the authenticated panel. Save changes after validation; use **Configuration history** to compare or restore an earlier revision. Some listeners are process-owned and require restart to change. Configuration updates are not a replacement for encrypted full backups.
|
||||
|
||||
## JSON file as authoritative configuration (0.34.1 DEV)
|
||||
## Configuration storage: SQLite or JSON file
|
||||
|
||||
**Settings → Manual config** shows the active storage mode and path, sourced from the read-only `storage` member of the authenticated `GET /api/config` response (`revision`, `config`, `storage`). With no `--config`, the authoritative configuration is in `<data-dir>/config.sqlite3` (normally `/var/lib/rustproxy/config.sqlite3`). With `--config`, that JSON file is authoritative, while SQLite still stores revision history, accounts and audit records. Switching modes requires a service restart; the panel does not change the startup argument.
|
||||
|
||||
### Optional JSON configuration source
|
||||
|
||||
Start the process with an **existing**, absolute JSON config filename, for example:
|
||||
|
||||
@@ -12,7 +16,9 @@ rust-proxy --data-dir /var/lib/rustproxy --config /etc/rustproxy/config.json ser
|
||||
|
||||
`RUST_PROXY_CONFIG=/etc/rustproxy/config.json` is an equivalent global setting. The file must be a regular file (not a symlink) within the configuration size limit and readable/writable by the service account; its parent directory must permit creation/renaming for atomic updates. The file is the canonical desired configuration. Panel and API edits, including history restore, rewrite it; SQLite retains revisions and audit. RustProxy rejects panel saves after an unimported external file edit rather than clobbering it. Use `rust-proxy reload` or `rust-proxy config reload` to import such edits after validation. No `--config` flag keeps the original SQLite-owned configuration behavior.
|
||||
|
||||
For a systemd deployment, put `RUST_PROXY_CONFIG=/etc/rustproxy/config.json` into the private EnvironmentFile referenced by the unit, or add `--config ...` to `ExecStart`. Use `systemctl reload rustproxy` after manual edits; the example `ExecReload` calls the CLI. Keep write access to the file and directory narrowly restricted. Hot reload cannot change a process-owned listener's bind/address or ALPN without restart.
|
||||
For a systemd deployment, use `systemctl edit rustproxy` to add `--config /etc/rustproxy/config.json` to `ExecStart` (with a reset line `ExecStart=`), or supply `RUST_PROXY_CONFIG` through the unit's private EnvironmentFile. **Use an exported, complete JSON document before enabling the flag; an absent/empty file prevents startup.** The example below is in [Installation — optional systemd JSON file](INSTALL.md#optional-systemd-json-configuration). It includes `chown`, POSIX ACLs on both file and parent directory, and `ReadWritePaths=` for hardened services: RustProxy atomically replaces the JSON and therefore needs **write plus traversal permissions on the directory**, not merely a writable file. The resulting file will normally be owned by `rustproxy` with mode `0600` after its first panel save.
|
||||
|
||||
Check the effective unit with `systemctl cat rustproxy`, paths/ACLs with `getfacl`, and storage mode under **Settings → Manual config**. Manual file edits require `systemctl reload rustproxy` to import changes; a successful panel save already updates the file. Listener binds/ALPN still require a restart. Back up both the JSON source **and** the SQLite database/other private state; history is not a complete backup.
|
||||
|
||||
|
||||
## Configuration map
|
||||
|
||||
+3
-3
@@ -7,12 +7,12 @@ The included `Dockerfile` compiles RustProxy with a **Rust 1.99** build image an
|
||||
Run from the repository root:
|
||||
|
||||
```bash
|
||||
docker build -t rustproxy:0.34.1 .
|
||||
docker build -t rustproxy:0.34.2 .
|
||||
docker volume create rustproxy-data
|
||||
docker run -d --name rustproxy \
|
||||
-p 8080:8080 \
|
||||
-v rustproxy-data:/var/lib/rustproxy \
|
||||
rustproxy:0.34.1
|
||||
rustproxy:0.34.2
|
||||
```
|
||||
|
||||
In the image, the default HTTP frontend binds `0.0.0.0:8080`. The admin listener defaults to `127.0.0.1:9090` **inside the container**. Simply publishing container port 9090 does not make that loopback listener reachable from a remote host. Initialize the administrator from a local container shell:
|
||||
@@ -35,4 +35,4 @@ For Docker-based application discovery, install the **separate Docker agent** on
|
||||
|
||||
## Upgrade and validate
|
||||
|
||||
Build a reviewed new image, preserve the volume, make an encrypted application backup and deploy with a maintenance window. Verify configuration compatibility, listener reachability, frontend certificates, backup/restore and live traffic. The supplied 0.34.1 development source candidate is not itself a production-tested OCI image.
|
||||
Build a reviewed new image, preserve the volume, make an encrypted application backup and deploy with a maintenance window. Verify configuration compatibility, listener reachability, frontend certificates, backup/restore and live traffic. The supplied 0.34.2 development source candidate is not itself a production-tested OCI image.
|
||||
+57
-1
@@ -86,6 +86,62 @@ Then visit `http://127.0.0.1:9090` on your workstation. For a directly reachable
|
||||
- Listener bindings supplied explicitly via service arguments/systemd are locked against panel changes. Network bind, administration TLS and some monitoring changes take effect after a restart.
|
||||
- Ports below 1024 need the appropriate OS privileges/capability; use the installed service model rather than running the whole application as root.
|
||||
|
||||
## Optional systemd JSON configuration
|
||||
|
||||
This is **optional**. Without `--config`, RustProxy keeps its active configuration in `/var/lib/rustproxy/config.sqlite3` (SQLite). With `--config`, panel/API saves and history restores write `/etc/rustproxy/config.json` atomically; SQLite still contains history, administrator state and audit entries. In **Settings → Manual config** you can see which mode and path are active.
|
||||
|
||||
1. First export your existing, validated **full configuration** (do not start with `{}` on an established host). On the running instance with administration reachable at `127.0.0.1:9090`, use a privileged shell with `set -o pipefail`:
|
||||
|
||||
```bash
|
||||
sudo install -d -o root -g root -m 0700 /etc/rustproxy
|
||||
sudo install -o root -g root -m 0600 /dev/null /etc/rustproxy/config.json
|
||||
sudo -u rustproxy /usr/bin/rust-proxy --data-dir /var/lib/rustproxy \
|
||||
--admin-listen 127.0.0.1:9090 config get | sudo tee /etc/rustproxy/config.json >/dev/null
|
||||
```
|
||||
|
||||
If the installed binary is at `/opt/rustproxy/current/rust-proxy`, use that path in **both** commands and the override. The export requires an existing initialized administrator. You may instead use **Settings → Manual config → Export JSON**, then install that file securely with `sudo install -o root -g root -m 0600 exported.json /etc/rustproxy/config.json`.
|
||||
|
||||
2. Keep the directory and initial file owned by `root`, allow only the RustProxy service identity through **named POSIX ACLs** (install the `acl` package first, e.g. `sudo apt-get install acl` on Debian, to obtain `setfacl`/`getfacl`). The directory needs `rwx` for atomic create/rename; the original JSON needs `rw` for startup and backup tools. `root` retains ownership until the first atomic panel save, after which the new `0600` file is normally owned by `rustproxy`:
|
||||
|
||||
```bash
|
||||
sudo chown root:root /etc/rustproxy /etc/rustproxy/config.json
|
||||
sudo chmod 0700 /etc/rustproxy
|
||||
sudo chmod 0600 /etc/rustproxy/config.json
|
||||
sudo setfacl -m u:rustproxy:rwx /etc/rustproxy
|
||||
sudo setfacl -m u:rustproxy:rw- /etc/rustproxy/config.json
|
||||
sudo getfacl /etc/rustproxy /etc/rustproxy/config.json
|
||||
sudo -u rustproxy test -r /etc/rustproxy/config.json
|
||||
sudo -u rustproxy test -w /etc/rustproxy
|
||||
```
|
||||
|
||||
Never make `/etc/rustproxy` world-writable. RustProxy checks that `--config` is an existing absolute **regular non-symlink** file. The parent directory must be on a filesystem that supports atomic rename. Restoring a file as root may require reapplying its named ACL; atomic saves generate a new owner-only `0600` file.
|
||||
|
||||
3. Edit the systemd drop-in with `sudo systemctl edit rustproxy` and add the following example (the binary path must match your installation):
|
||||
|
||||
```ini
|
||||
[Service]
|
||||
ExecStart=
|
||||
ExecStart=/usr/bin/rust-proxy --data-dir /var/lib/rustproxy --admin-listen 0.0.0.0:9090 serve --proxy-listen 0.0.0.0:80 --tls-listen 0.0.0.0:443 --allow-remote-admin --config /etc/rustproxy/config.json
|
||||
ReadWritePaths=/etc/rustproxy
|
||||
```
|
||||
|
||||
`ReadWritePaths=` is needed when the unit has `ProtectSystem=strict`; it does **not** grant Unix file permissions, hence the ACLs above. An existing `ExecReload` can remain; it reloads through the local control API. Keep the existing unit's sandboxing, state/log writable paths, network capabilities and runtime user. Do not expose the example's `0.0.0.0:9090` admin listener over plaintext on an untrusted network: enable administration HTTPS and strict network controls first, or use the safer `127.0.0.1:9090` binding without `--allow-remote-admin`.
|
||||
|
||||
4. Verify and restart during a maintenance window:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl cat rustproxy
|
||||
sudo systemd-analyze verify rustproxy.service
|
||||
sudo systemctl restart rustproxy
|
||||
sudo systemctl status rustproxy
|
||||
sudo journalctl -u rustproxy -n 60 --no-pager
|
||||
```
|
||||
|
||||
Confirm in **Settings → Manual config** that the source is **JSON file** and the path is `/etc/rustproxy/config.json`. Save a harmless edit and confirm that the file is rewritten and readable by `rustproxy`; check that a revision appears in SQLite. To import a deliberate external file edit without restarting, run `sudo systemctl reload rustproxy` (if the unit has `ExecReload`) or `rust-proxy --data-dir /var/lib/rustproxy --admin-listen 127.0.0.1:9090 config reload`. The file is not watched automatically. An incompatible external edit must fail validation rather than silently overwrite the live configuration.
|
||||
|
||||
For the alternate environment-variable method, set `RUST_PROXY_CONFIG=/etc/rustproxy/config.json` in the service's protected EnvironmentFile. Do not set **both** unrelated config paths. See [Configuration](CONFIGURATION.md) and the [deployment example](../deploy/README.md).
|
||||
|
||||
## Managed update
|
||||
|
||||
Test the new build first. Then execute:
|
||||
@@ -105,4 +161,4 @@ The managed certificate service can create a private Python/Certbot environment
|
||||
|
||||
Verify `systemctl status rustproxy` and `journalctl -u rustproxy` (managed systemd), the panel login, frontend certificates, first Vhost, real backend response, access policies, optional QUIC, current logs and a full backup/restore test. For error diagnosis, consult [Troubleshooting](TROUBLESHOOTING.md).
|
||||
|
||||
**Release verification:** supplied 0.34.0 source changes still require target-platform compilation and functional acceptance before Internet-facing production use.
|
||||
**Release verification:** RustProxy 0.34.2 is a source package; complete a Rust 1.99+ build and target-platform HTTP/systemd/security acceptance tests before Internet-facing production use.
|
||||
+3
-3
@@ -1,12 +1,12 @@
|
||||
# RustProxy documentation
|
||||
|
||||
Practical guides for **RustProxy 0.34.1**. This index and the listed pages are also available in the authenticated panel at **`/docs → Reader`**. The adjacent **API** tab provides the embedded OpenAPI reference. Paths below are links to actual files in the source archive.
|
||||
Practical guides for **RustProxy 0.34.2**. This index and the listed pages are also available in the authenticated panel at **`/docs → Reader`**. The adjacent **API** tab provides the embedded OpenAPI reference. Paths below are links to actual files in the source archive.
|
||||
|
||||
## Getting started
|
||||
|
||||
- [Installation and updates](INSTALL.md) — packages, build, first administrator, systemd and updates.
|
||||
- [Installation and updates](INSTALL.md) — packages, build, first administrator, optional JSON/systemd permissions and updates.
|
||||
- [Container deployment](CONTAINER.md) — image, persistent state, ports and isolation.
|
||||
- [Settings and configuration](CONFIGURATION.md) — what to configure and which changes need restart.
|
||||
- [Settings and configuration](CONFIGURATION.md) — active SQLite/file storage source and which changes need restart.
|
||||
- [Troubleshooting](TROUBLESHOOTING.md) — symptom-based checks and release validation.
|
||||
|
||||
## Publishing services
|
||||
|
||||
+3
-1
@@ -44,7 +44,9 @@ An optional bounded Apache-style `.htaccess` compatibility layer supports a **su
|
||||
|
||||
A Web Service may enable PHP via a shared PHP-FPM profile or its own configuration. PHP is executed by the FPM service, not RustProxy, and must not be exposed as a raw Internet port. Use dedicated pools for different applications. See [PHP-FPM](PHP_FPM.md).
|
||||
|
||||
Vhosts can intercept selected application error bodies in **Pages** and return a configured HTML error page while preserving the status. Internal location `error_fallback` is different: it routes the error to a named internal handler. Error-page replacements are marked uncacheable.
|
||||
Missing static files return normal **HTTP 404 Not Found**, unreadable/blocked paths **403 Forbidden**, unsupported static methods **405 Method Not Allowed** (with `Allow: GET, HEAD`), and internal failures **500 Internal Server Error**. Generated response bodies contain only the standard status, not a `RustProxy: Web Server ...` diagnostic. `HEAD` errors have no response body. Internal server errors can be diagnosed through service logs; generated responses are not cacheable by default.
|
||||
|
||||
Vhosts can intercept selected application error bodies in **Pages** and return a configured HTML error page while preserving the status. Internal location `error_fallback` is different: it routes the error to a named internal handler. Error-page replacements are marked uncacheable. Origin-supplied and explicitly configured custom error bodies are preserved unless interception is enabled.
|
||||
|
||||
## Monitoring and issues
|
||||
|
||||
|
||||
Reference in new issue
Block a user