Releases: csd113/RustHost
Releases · csd113/RustHost
v0.1.0
Changelog
All notable changes to RustHost are documented here.
[0.1.0] — Initial Release
HTTP Server
- Custom HTTP/1.1 static file server built directly on
tokio::net::TcpListener— no third-party HTTP framework dependency. - Serves
GETandHEADrequests; all other methods return400 Bad Request. - Percent-decoding of URL paths (e.g.
%20→ space) before file resolution. - Query string and fragment stripping before path resolution.
- Path traversal protection: every resolved path is verified to be a descendant of the site root via
std::fs::canonicalize; any attempt to escape (e.g./../secret) is rejected withHTTP 403 Forbidden. - Request header size cap of 8 KiB; oversized requests are rejected immediately.
Content-Type,Content-Length, andConnection: closeheaders on every response.- Configurable index file (default:
index.html) served for directory requests. - Optional HTML directory listing for directory requests when no index file is found, with alphabetically sorted entries.
- Built-in "No site found" fallback page (HTTP 200) when the site directory is empty and directory listing is disabled, so the browser always shows a helpful message rather than a connection error.
- Placeholder
index.htmlwritten on first run so the server is immediately functional out of the box. - Automatic port fallback: if the configured port is in use, the server silently tries the next free port up to 10 times before giving up (configurable via
auto_port_fallback). - Configurable bind address; defaults to
127.0.0.1(loopback only) with a logged warning when set to0.0.0.0. - Per-connection Tokio tasks so concurrent requests never block each other.
MIME Types
- Built-in extension-to-MIME mapping with no external dependency, covering:
- Text:
html,htm,css,js,mjs,txt,csv,xml,md - Data:
json,jsonld,pdf,wasm,zip - Images:
png,jpg/jpeg,gif,webp,svg,ico,bmp,avif - Fonts:
woff,woff2,ttf,otf - Audio:
mp3,ogg,wav - Video:
mp4,webm - Unknown extensions fall back to
application/octet-stream.
- Text:
Tor Onion Service (Arti — in-process)
- Embedded Tor support via Arti, the official Rust Tor implementation — no external
torbinary ortorrcfile required. - Bootstraps to the Tor network in a background Tokio task; never blocks the HTTP server or console.
- First run downloads approximately 2 MB of directory consensus data (approximately 30 seconds); subsequent runs reuse the cache and start in seconds.
- Stable
.onionaddress across restarts: the service keypair is persisted torusthost-data/arti_state/; deleting this directory rotates to a new address. - Consensus cache stored in
rusthost-data/arti_cache/for fast startup. - Onion address encoded in-process using the v3
.onionspec (SHA3-256 checksum + base32) — no dependency on Arti'sDisplayRedactedformatting. - Each inbound Tor connection is bridged to the local HTTP server via
tokio::io::copy_bidirectionalin its own Tokio task. - Tor subsystem can be disabled entirely with
[tor] enabled = false; the dashboard onion section reflects this immediately. - Graceful shutdown: the
TorClientis dropped naturally when the Tokio runtime exits, closing all circuits cleanly — no explicit kill step needed. .onionaddress displayed in the dashboard and logged in a prominent banner once the service is active.
Interactive Terminal Dashboard
- Full-screen raw-mode terminal UI built with crossterm; no external TUI framework.
- Three screens navigable with single-key bindings:
- Dashboard (default) — live status overview.
- Log view — last 40 log lines, toggled with
[L]. - Help overlay — key binding reference, toggled with
[H]; any other key dismisses it.
- Dashboard sections:
- Status — local server state (RUNNING with bind address and port, or STARTING) and Tor state (DISABLED / STARTING / READY / FAILED with exit code).
- Endpoints — local
http://localhost:<port>URL and Tor.onionURL (or a dim status hint if Tor is not yet ready). - Site — directory path, file count, and total size (auto-scaled to B / KB / MB / GB).
- Activity — total request count and error count (errors highlighted in red when non-zero).
- Key bar — persistent one-line reminder of available key bindings.
- Dashboard redraws at a configurable interval (default: 500 ms).
- Log view supports optional
HH:MM:SStimestamp display, toggled viashow_timestampsin config. - Customisable instance name shown in the dashboard header (max 32 characters).
- Headless / non-interactive mode: set
[console] interactive = falsefor systemd or piped deployments; the server prints a plainhttp://…line to stdout instead. - Graceful terminal restore on fatal crash: raw mode is disabled and the cursor is shown even if the process exits unexpectedly.
Configuration
- TOML configuration file (
rusthost-data/settings.toml) with six sections:[server],[site],[tor],[logging],[console],[identity]. - Configuration validated at startup with clear, multi-error messages before any subsystem is started.
- Validated fields include port range, bind IP address format, index file name (no path separators), log level, console refresh rate minimum (100 ms), instance name length (1–32 chars), and absence of control characters in the name.
- Full default config written automatically on first run with inline comments explaining every option.
- Reloading site stats (file count and total size) without restart via
[R]in the dashboard.
Logging
- Custom
log::Logimplementation; all modules use the standardlogfacade macros (log::info!,log::warn!, etc.). - Dual output: log file on disk (append mode, parent directories created automatically) and an in-memory ring buffer.
- Ring buffer holds the most recent 1 000 lines and feeds the console log view without any file I/O on each render tick.
- Log file path configurable relative to
rusthost-data/; defaults tologs/rusthost.log. - Configurable log level:
trace,debug,info,warn,error. - Timestamped entries in
[LEVEL] [HH:MM:SS] messageformat. - Logging can be disabled entirely (
[logging] enabled = false) for minimal-overhead deployments.
Lifecycle and Startup
- First-run detection: if
rusthost-data/settings.tomldoes not exist, RustHost initialises the data directory (site/,logs/), writes defaults, drops a placeholderindex.html, prints a short getting-started guide, and exits cleanly — no daemon started. - Normal run startup sequence: load and validate config → initialise logging → build shared state → scan site directory → bind HTTP server → start Tor (if enabled) → start console → open browser (if configured) → enter event loop.
- Shutdown triggered by
[Q]keypress orSIGINT/SIGTERM(viactrlc); sends a watch-channel signal to the HTTP server and console, then waits 300 ms for in-flight connections before exiting. - Optional browser launch at startup (
open_browser_on_start); usesopen(macOS),explorer(Windows), orxdg-open(Linux/other). - All subsystems share state through an
Arc<RwLock<AppState>>; hot-path request and error counters use separateArc<Metrics>backed by atomics so the HTTP handler never acquires a lock per request.
Project and Build
- Single binary; no installer, no runtime dependencies beyond the binary itself (Tor included via Arti).
- Data directory co-located with the binary at
./rusthost-data/; entirely self-contained. - Minimum supported Rust version: 1.86 (required by
arti-client 0.40). - Release profile:
opt-level = 3, LTO enabled, debug symbols stripped. cargo-denyconfiguration (deny.toml) enforcing allowed SPDX licenses (MIT, Apache-2.0, Apache-2.0 WITH LLVM-exception, Zlib, Unicode-3.0) and advisory database checks; known transitive duplicate crates (mio,windows-sys) skipped with comments.- Advisory
RUSTSEC-2023-0071(RSA Marvin timing attack) acknowledged and suppressed with a documented rationale: thersacrate is a transitive dependency ofarti-clientused exclusively for RSA signature verification on Tor directory consensus documents, not decryption; the attack's threat model does not apply.
First functional Release
HTTP Server
- Custom HTTP/1.1 static file server built directly on
tokio::net::TcpListener— no third-party HTTP framework dependency. - Serves
GETandHEADrequests; all other methods return400 Bad Request. - Percent-decoding of URL paths (e.g.
%20→ space) before file resolution. - Query string and fragment stripping before path resolution.
- Path traversal protection: every resolved path is verified to be a descendant of the site root via
std::fs::canonicalize; any attempt to escape (e.g./../secret) is rejected withHTTP 403 Forbidden. - Request header size cap of 8 KiB; oversized requests are rejected immediately.
Content-Type,Content-Length, andConnection: closeheaders on every response.- Configurable index file (default:
index.html) served for directory requests. - Optional HTML directory listing for directory requests when no index file is found, with alphabetically sorted entries.
- Built-in "No site found" fallback page (HTTP 200) when the site directory is empty and directory listing is disabled, so the browser always shows a helpful message rather than a connection error.
- Placeholder
index.htmlwritten on first run so the server is immediately functional out of the box. - Automatic port fallback: if the configured port is in use, the server silently tries the next free port up to 10 times before giving up (configurable via
auto_port_fallback). - Configurable bind address; defaults to
127.0.0.1(loopback only) with a logged warning when set to0.0.0.0. - Per-connection Tokio tasks so concurrent requests never block each other.
MIME Types
- Built-in extension-to-MIME mapping with no external dependency, covering:
- Text:
html,htm,css,js,mjs,txt,csv,xml,md - Data:
json,jsonld,pdf,wasm,zip - Images:
png,jpg/jpeg,gif,webp,svg,ico,bmp,avif - Fonts:
woff,woff2,ttf,otf - Audio:
mp3,ogg,wav - Video:
mp4,webm - Unknown extensions fall back to
application/octet-stream.
- Text:
Interactive Terminal Dashboard
- Full-screen raw-mode terminal UI built with crossterm; no external TUI framework.
- Three screens navigable with single-key bindings:
- Dashboard (default) — live status overview.
- Log view — last 40 log lines, toggled with
[L]. - Help overlay — key binding reference, toggled with
[H]; any other key dismisses it.
- Dashboard sections:
- Status — local server state (RUNNING with bind address and port, or STARTING) and Tor state (DISABLED / STARTING / READY / FAILED with exit code).
- Endpoints — local
http://localhost:<port>URL and Tor.onionURL (or a dim status hint if Tor is not yet ready). - Site — directory path, file count, and total size (auto-scaled to B / KB / MB / GB).
- Activity — total request count and error count (errors highlighted in red when non-zero).
- Key bar — persistent one-line reminder of available key bindings.
- Dashboard redraws at a configurable interval (default: 500 ms).
- Log view supports optional
HH:MM:SStimestamp display, toggled viashow_timestampsin config. - Customisable instance name shown in the dashboard header (max 32 characters).
- Headless / non-interactive mode: set
[console] interactive = falsefor systemd or piped deployments; the server prints a plainhttp://…line to stdout instead. - Graceful terminal restore on fatal crash: raw mode is disabled and the cursor is shown even if the process exits unexpectedly.
Configuration
- TOML configuration file (
rusthost-data/settings.toml) with six sections:[server],[site],[tor],[logging],[console],[identity]. - Configuration validated at startup with clear, multi-error messages before any subsystem is started.
- Validated fields include port range, bind IP address format, index file name (no path separators), log level, console refresh rate minimum (100 ms), instance name length (1–32 chars), and absence of control characters in the name.
- Full default config written automatically on first run with inline comments explaining every option.
- Reloading site stats (file count and total size) without restart via
[R]in the dashboard.
Logging
- Custom
log::Logimplementation; all modules use the standardlogfacade macros (log::info!,log::warn!, etc.). - Dual output: log file on disk (append mode, parent directories created automatically) and an in-memory ring buffer.
- Ring buffer holds the most recent 1 000 lines and feeds the console log view without any file I/O on each render tick.
- Log file path configurable relative to
rusthost-data/; defaults tologs/rusthost.log. - Configurable log level:
trace,debug,info,warn,error. - Timestamped entries in
[LEVEL] [HH:MM:SS] messageformat. - Logging can be disabled entirely (
[logging] enabled = false) for minimal-overhead deployments.
Lifecycle and Startup
- First-run detection: if
rusthost-data/settings.tomldoes not exist, RustHost initialises the data directory (site/,logs/), writes defaults, drops a placeholderindex.html, prints a short getting-started guide, and exits cleanly — no daemon started. - Normal run startup sequence: load and validate config → initialise logging → build shared state → scan site directory → bind HTTP server → start Tor (if enabled) → start console → open browser (if configured) → enter event loop.
- Shutdown triggered by
[Q]keypress orSIGINT/SIGTERM(viactrlc); sends a watch-channel signal to the HTTP server and console, then waits 300 ms for in-flight connections before exiting. - Optional browser launch at startup (
open_browser_on_start); usesopen(macOS),explorer(Windows), orxdg-open(Linux/other). - All subsystems share state through an
Arc<RwLock<AppState>>; hot-path request and error counters use separateArc<Metrics>backed by atomics so the HTTP handler never acquires a lock per request.
Project and Build
- Single binary; no installer, no runtime dependencies beyond the binary itself (Tor included via Arti).
- Data directory co-located with the binary at
./rusthost-data/; entirely self-contained. - Minimum supported Rust version: 1.86 (required by
arti-client 0.40). - Release profile:
opt-level = 3, LTO enabled, debug symbols stripped. cargo-denyconfiguration (deny.toml) enforcing allowed SPDX licenses (MIT, Apache-2.0, Apache-2.0 WITH LLVM-exception, Zlib, Unicode-3.0) and advisory database checks; known transitive duplicate crates (mio,windows-sys) skipped with comments.- Advisory
RUSTSEC-2023-0071(RSA Marvin timing attack) acknowledged and suppressed with a documented rationale: thersacrate is a transitive dependency ofarti-clientused exclusively for RSA signature verification on Tor directory consensus documents, not decryption; the attack's threat model does not apply.