nano-web
Static file server built with Rust. Serves files from memory with pre-compressed variants.
Performance
130,000+ requests/sec with sub-millisecond latency:
- Axum/Hyper HTTP stack
- Files pre-compressed at startup (brotli/gzip/zstd)
- Lock-free concurrent HashMap routing
- Zero-copy serving with Bytes
Benchmark (M3 Max):
Features
- In-memory file serving with compression
- Security headers
- SPA mode with index.html fallback
- Dev mode with file watching
- Health endpoint at
/_health - Runtime environment variable injection
- JSON/console logging
- Docker images under 20MB
📦 Installation
Install with Mise (via ubi)
Install with Cargo
Download Binary
Pre-built binaries available on GitHub Releases.
🐳 Docker
Multi-arch images available:
FROM ghcr.io/radiosilence/nano-web:latest
COPY ./dist /public/
Production example:
FROM node:lts-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
FROM ghcr.io/radiosilence/nano-web:latest
COPY --from=builder /app/dist/ /public/
EXPOSE 3000
🔧 Usage
# Serve files from ./public/ on port 3000
# Custom directory and port
# SPA mode with dev reloading
# See all options
⚙️ Configuration
| Variable | CLI Flag | Default | Description |
|---|---|---|---|
PORT |
--port, -p |
3000 |
Port to listen on |
--spa |
--spa |
false |
Enable SPA mode (serve index.html for 404s) |
--dev |
--dev, -d |
false |
Enable dev mode (hot-reload files) |
CONFIG_PREFIX |
--config-prefix |
VITE_ |
Environment variable injection prefix |
LOG_LEVEL |
--log-level |
info |
Logging: debug, info, warn, error |
LOG_FORMAT |
--log-format |
console |
Format: json or console |
LOG_REQUESTS |
--log-requests |
true |
Enable request logging |
Environment Variables
# Docker example
⚡ Runtime Environment Injection
Inject configuration at runtime without rebuilding:
<!-- Your index.html -->
// Your app
const { API_URL } = JSON.parse(window.ENV);
# Same build, different configs
Template Engine
Uses MiniJinja template syntax for environment variable injection. Variables available:
{{env.VARIABLE_NAME}}- Direct variable access{{Json}}- Raw JSON string of all prefixed variables{{EscapedJson}}- JSON-escaped for inline JavaScript
🏥 Health Checks
Built-in health endpoint at /_health:
📊 Logging
Console format (default):
2025-01-15T10:30:45Z INFO nano_web: Starting server on 0.0.0.0:3000
2025-01-15T10:30:45Z INFO nano_web: Routes loaded: 15
JSON format for log aggregation:
🛠️ Building from Source
# Clone and build
# Run tests
# Run benchmarks
Development
# Development server with hot-reload
# Watch for changes
🌰 Advanced: Unikernels
Deploy as unikernels with Nanos:
Architecture
- HTTP: Axum + Hyper
- Routing: Lock-free DashMap with FxHash
- Compression: Parallel pre-compression at startup
- Memory: Zero-copy serving with Bytes
- Security: Path validation, security headers
- Runtime: Tokio async
Compared to previous Go version: 70% faster (130k vs 76k req/sec), lower latency, no GC overhead.
📄 License
Licensed under the MIT License - see LICENSE for details.
🙏 Acknowledgments
- Axum - Ergonomic async web framework
- Hyper - Fast HTTP implementation
- Tokio - Asynchronous runtime
- DashMap - Lock-free concurrent HashMap
- Brotli - Compression library