Unified reverse proxy and static hosting automation framework powered by Nginx
oneserver is an automation utility that compiles a single, human-readable settings.json file into highly optimized, production-ready Nginx proxy configurations (nginx-proxy.conf). It supports standard reverse proxying, high-performance static file hosting, temporary/permanent redirects, custom error pages, and fine-grained rate limiting.
- π― Unified Configuration: Define all domains, SSL keys, timeouts, rate limits, error pages, and routing paths in a single JSON file.
- β‘ Static File Hosting: High-performance static serving directly from Nginx with advanced path-to-file mapping rules.
- π Custom Redirects: Seamless temporary (302) and permanent (301) redirection with optional path forwarding.
- π Security Hardening: Generates modern SSL/TLS configurations, strict security headers (CSP, HSTS, X-Frame-Options), and gzip compression.
- π¦ Per-Domain Rate Limiting: Limit request traffic globally or per-path with burst handling and nodelay configurations.
- π οΈ Custom Error Pages: Domain-scoped error handlers mapping HTTP status codes (or
*fallbacks) to custom static pages or redirects. - π Real IP Resolution: Pre-configured to trust private and Docker bridge networks (
172.16.0.0/12, etc.) to extract client IPs fromX-Forwarded-For. β οΈ WSL2 Networking Checks: Automatically detects WSL VM network settings and warns if running in NAT mode instead of mirrored mode.
oneserver includes an interactive, browser-based editor located in settings-editor/index.html.
You can open this file in any web browser to:
- Load, view, and modify your existing
settings.json. - Add, remove, or configure routing, redirections, and static paths visually.
- Export the validated JSON configuration.
Create a settings.json file in the root directory (see settings.json.example for a complete template). Comments using // are fully supported:
[
{
"domain": "app.example.com",
"forwarding": "host.docker.internal:3000",
"type": "https-only"
}
]Run the Python compilation script:
python3 generate_nginx_config.pyThis generates the optimized nginx-proxy.conf.
Reload or restart your Nginx container:
docker compose exec oneserver nginx -t && docker compose restart oneserverEach domain configuration object in the settings array supports the following fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
domain |
String | Yes | - | The domain name to serve (e.g. app.example.com). |
forwarding |
String | Yes* | - | Backend address (host:port). Not required for static hosting types. |
type |
String | No | "https-only" |
Server type. Supports: "http", "https", "https-only", "redirect-temp", "redirect-perm", "static-http", "static-https", or "static-https-only". |
| Field | Type | Default | Description |
|---|---|---|---|
ca-bundle |
String | Auto-inferred | Relative path to SSL certificate file (e.g. fullchain.pem). Required for secure redirects and static HTTPS. |
private-key |
String | Auto-inferred | Relative path to SSL private key file (e.g. privkey.pem). Required for secure redirects and static HTTPS. |
security-headers |
Boolean | true |
Enables HSTS, X-Frame-Options, X-Content-Type-Options, etc. |
csp-unsafe-eval |
Boolean | false |
Allows unsafe-eval in the Content Security Policy header. |
csp-wildcard |
Boolean | false |
Relaxes CSP constraints to allow wildcards in source mappings. |
no-x-forwarded-for |
Boolean | false |
If true, Nginx will omit the X-Forwarded-For and X-Real-IP proxy headers from requests to the backend. |
no-x-forwarded-host |
Boolean | false |
If true, Nginx will omit the X-Forwarded-Host proxy header from requests to the backend. |
| Field | Type | Default | Description |
|---|---|---|---|
rate-limit |
Num / Dict | - | Rate limit per minute. Pass a number for global limit, or a path-to-limit dictionary. |
websocket |
Boolean | true |
Configures upstream connection upgrade headers for WebSocket support. |
compression |
Boolean | true |
Enables Gzip compression for static files and API payloads. |
timeout |
String | "120s" |
Connection timeout limit (e.g., "60s", "5m"). |
max-body-size |
String | "10m" |
Maximum allowed request client body size (e.g., "50g", "500m"). |
allowed-paths |
Array | [] |
Whitelist of allowed path prefixes. Other paths return a 404 (or 403). |
path |
Dict | {} |
Route-to-file mappings (required for static serving types). |
forward-url-path |
Boolean | false |
If true, the requested URL path is appended to the forwarding target on redirects. |
service |
String | "" |
Tag/identifier associated with the target backend service. |
Note
Snake_case variant keys (e.g. rate_limit, ca_bundle, private_key, security_headers, csp_unsafe_eval, csp_wildcard, max_body_size, allowed_paths, proxy_buffering_off, proxy_cache_off, no_x_forwarded_for, no_x_forwarded_host, forward_url_path) are fully compatible and normalized automatically.
By using redirect-temp (302) or redirect-perm (301), you can configure high-performance redirects at the proxy level:
{
"domain": "short.url",
"forwarding": "https://target-domain.com/landing",
"type": "redirect-perm",
"forward-url-path": true,
"ca-bundle": "fullchain.pem",
"private-key": "privkey.pem"
}- With
forward-url-path: false(default): Visitingshort.url/helloredirects directly tohttps://target-domain.com/landing. - With
forward-url-path: true: Visitingshort.url/helloredirects tohttps://target-domain.com/landing/hello.
Static serving handles route-to-file mappings relative to the /public directory inside the Nginx container:
{
"domain": "static.example.com",
"type": "static-https-only",
"ca-bundle": "fullchain.pem",
"private-key": "privkey.pem",
"path": {
"/hello": "hello.html",
"/hello/": "hello/",
"/hello/*": "hello.html",
"/hello/**": "hello.html"
}
}- Exact Match (
/hello): Serves/public/hello.htmlexactly. - Directory Prefix (
/hello/): Serves files under/public/hello/. - Single-Segment Wildcard (
/hello/*): Matches/hello/abc, but deeper routes (e.g./hello/abc/def) return a 404. - Recursive Wildcard (
/hello/**): Matches all subpaths at any depth (e.g.,/hello/abc/def/ghi).
[!ERROR] The path generator validates mappings at compile time. Source paths without a trailing slash (e.g.,
/hello) mapping to directory targets (e.g.,hello/) will throw an error, as will defining conflicting wildcards (/*and/**) on the same base path.
Error handlers can be configured per domain by prefixing the type with {code}: or *::
[
{
"domain": "app.example.com",
"type": "https-only",
"forwarding": "localhost:3000"
},
{
"domain": "app.example.com",
"type": "404:redirect-perm",
"forwarding": "https://example.com/not-found"
},
{
"domain": "app.example.com",
"type": "500:static-https",
"ca-bundle": "fullchain.pem",
"private-key": "privkey.pem",
"path": {
"/": "errors/500.html"
}
},
{
"domain": "app.example.com",
"type": "*:static-http",
"path": {
"/": "errors/fallback.html"
}
}
]- Specific Codes: If Nginx or the backend returns
404or500, Nginx intercepts the response and applies the redirect or serves the static error page. - Wildcard Fallback (
*): Handles all other error status codes (400, 403, 502, 503, 504) through a single fallback page. - Nginx Fallback: If no wildcard handler is defined, unhandled error codes fall back to Nginx's default error pages.
To allow Nginx to natively resolve backend containers by their service names, oneserver runs attached to the oneserver_bridge network inside docker-compose.yml:
services:
oneserver:
build:
context: .
dockerfile: Dockerfile
container_name: oneserver
ports:
- "80:80"
- "443:443"
volumes:
- ${ONESERVER_PWD:-.}/cert:/etc/nginx/ssl:ro
- ${ONESERVER_PWD:-.}/nginx-logs:/var/log/nginx
- ${ONESERVER_PWD:-.}/public:/public:ro
restart: unless-stopped
networks:
- oneserver_bridgeNote
Other services (like your API backend or app containers) should join the external oneserver_bridge network. This enables Nginx to forward requests directly using their container name and port (e.g. "forwarding": "api:8080").
If running oneserver inside Windows Subsystem for Linux (WSL2), Nginx's ability to see the real client IP address depends on your WSL configuration:
- NAT Mode (Default): WSL NATs all incoming connections. Nginx inside the container will see all client IPs as the virtual VM host gateway IP. The generator outputs a warning when NAT mode is detected.
- Mirrored Mode: Shares the Windows host's network interfaces directly with WSL. In this mode, Nginx receives connections with the real, original public client IP intact.
To enable mirrored networking, add the following to your %USERPROFILE%\.wslconfig in Windows:
[wsl2]
networkingMode=mirroredThen restart WSL by running wsl --shutdown in PowerShell.