# User Manual
- [Command line](#command-line)
- [Signals & reload](#signals)
- [Configuration file](#configuration)
- [Top-level directives](#top-level)
- [`events` block](#events)
- [`http` block](#http)
- [`server` block](#server)
- [`location` block](#location)
- [TLS / HTTPS](#tls)
- [Reverse proxy & load balancing](#proxy)
- [Logging](#logging)
- [Recipes](#recipes)
- [Feature support matrix](#support)
---
## <a id="command-line"></a>Command line
```text
veld [OPTIONS] [COMMAND]
COMMANDS:
start Start the server (default if omitted)
test Parse and validate the configuration, then exit
reload Tell a running instance to reload its configuration
OPTIONS:
-c, --config <PATH> Configuration file [default: conf/veld.conf]
-p, --prefix <PATH> Root prefix for relative paths in the config and for
the pid/log files [default: current directory]
--workers <N> Override worker_processes from the config
-h, --help Print help
-V, --version Print version
```
Examples:
```bash
veld -c /etc/veld/veld.conf test # validate only
veld -c /etc/veld/veld.conf start # run
veld -c /etc/veld/veld.conf --workers 8 start
veld -c /etc/veld/veld.conf reload # reload a running instance
```
Relative paths inside the config (e.g. `root html;`, `error_log logs/error.log;`) are
resolved against `--prefix` (default: the current working directory).
## <a id="signals"></a>Signals & reload
On Linux/Unix the server responds to signals (mirroring nginx):
| Signal | Effect |
|---|---|
| `SIGHUP` | Reload configuration |
| `SIGUSR1` | Reopen log files (log rotation) |
| `SIGTERM` / `SIGINT` | Graceful shutdown |
`veld ... reload` reads the pid file and sends `SIGHUP` for you. Under systemd, use
`systemctl reload veld` (the provided unit maps this to `SIGHUP`).
---
## <a id="configuration"></a>Configuration file
The configuration syntax is compatible with nginx: directives end with `;`, blocks use
`{ }`, and `#` starts a comment. Below are the directives veld understands.
### <a id="top-level"></a>Top-level directives
| Directive | Example | Meaning |
|---|---|---|
| `worker_processes` | `worker_processes auto;` | Number of worker tasks. `auto` = CPU cores. |
| `error_log` | `error_log logs/error.log warn;` | Error log path and level. |
| `pid` | `pid logs/veld.pid;` | PID file path. |
### <a id="events"></a>`events` block
```nginx
events {
worker_connections 4096; # max concurrent connections per worker
multi_accept on; # accept multiple connections per wakeup
}
```
### <a id="http"></a>`http` block
```nginx
http {
include mime.types; # load MIME type mappings
default_type application/octet-stream;
sendfile on; # zero-copy file transfer (Linux)
tcp_nopush on; # coalesce packets with sendfile
tcp_nodelay on; # disable Nagle (low latency)
keepalive_timeout 65; # seconds to keep idle connections
access_log logs/access.log main; # or: access_log off;
gzip on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript text/xml;
server { ... }
}
```
### <a id="server"></a>`server` block
```nginx
server {
listen 8080; # port (use "listen 443 ssl;" for HTTPS)
server_name localhost; # virtual host name(s); "_" = catch-all
root /var/www/site; # document root
index index.html index.htm; # index files for directory requests
location / { ... }
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}
```
Multiple `server` blocks are matched by `server_name` against the request `Host` header.
### <a id="location"></a>`location` block
Match types, in priority order:
| Syntax | Match |
|---|---|
| `location = /path` | Exact match |
| `location /path` | Prefix match (longest wins) |
| `location ~ regex` | Regex (case-sensitive) |
| `location ~* regex`| Regex (case-insensitive) |
```nginx
location / {
try_files $uri $uri/ =404; # try file, then directory, then 404
}
location /api/ {
proxy_pass backend; # forward to an upstream (see below)
}
location = /healthz {
return 200 "ok"; # return a fixed status (+ optional body)
}
```
Static-file features applied automatically: `ETag` / `If-None-Match` / `If-Modified-Since`
(304), `Range` requests (206), gzip/deflate for configured types, and an open-file cache.
### <a id="tls"></a>TLS / HTTPS
```nginx
server {
listen 443 ssl;
server_name example.com;
ssl_certificate certs/server.crt;
ssl_certificate_key certs/server.key;
ssl_protocols TLSv1.2 TLSv1.3;
root /var/www/site;
index index.html;
}
```
TLS is provided by [rustls](https://github.com/rustls/rustls). Generate a self-signed cert
for testing:
```bash
openssl req -x509 -newkey rsa:2048 -nodes -keyout certs/server.key \
-out certs/server.crt -days 365 -subj "/CN=localhost"
```
### <a id="proxy"></a>Reverse proxy & load balancing
```nginx
http {
upstream backend {
least_conn; # strategy (default: round-robin)
server 127.0.0.1:9001 weight=3; # weighted
server 127.0.0.1:9002;
server 127.0.0.1:9003 backup; # only used if others are down
}
server {
listen 8080;
location / {
proxy_pass backend;
}
}
}
```
Supported strategies: **round-robin**, **least-connections** (`least_conn`), and
**IP-hash** (`ip_hash`). Unhealthy upstreams are detected by health checks and skipped.
---
## <a id="logging"></a>Logging
- **Error log**: `error_log <path> <level>;` — levels `debug`, `info`, `warn`, `error`.
- **Access log**: `access_log <path> <format>;` or `access_log off;` to disable
(recommended for max throughput / benchmarking).
- **Console verbosity**: set `RUST_LOG` (e.g. `RUST_LOG=veld=debug`) to control the
tracing output of the foreground process.
- **Rotation**: move the log file aside, then `systemctl reload veld` (or send
`SIGUSR1`) to reopen.
---
## <a id="recipes"></a>Recipes
**Static site on port 80** (grant the bind capability once):
```bash
sudo setcap 'cap_net_bind_service=+ep' /usr/local/bin/veld
# listen 80; root /var/www/site;
```
**Max-throughput static config** (what the benchmarks use):
```nginx
worker_processes auto;
events { worker_connections 4096; multi_accept on; }
http {
sendfile on; tcp_nopush on; tcp_nodelay on;
keepalive_timeout 65; access_log off;
server { listen 8080; root /var/www/site; index index.html;
location / { try_files $uri $uri/ =404; } }
}
```
**Validate before reload** (zero-downtime safe):
```bash
veld -c /etc/veld/veld.conf test && systemctl reload veld
```
---
## <a id="support"></a>Feature support matrix
| Feature | Status |
|---|---|
| HTTP/1.1 (keep-alive, chunked) | ✅ |
| Static files (sendfile, range, ETag/conditional) | ✅ |
| Open-file cache | ✅ |
| gzip / deflate | ✅ |
| Directory autoindex | ✅ |
| Virtual hosts (`server_name`) | ✅ |
| Reverse proxy (`proxy_pass`) | ✅ |
| Load balancing (RR / least-conn / ip-hash) | ✅ |
| Health checks | ✅ |
| TLS 1.2 / 1.3 (rustls) | ✅ |
| URL rewrite / redirect | ✅ |
| Signals (reload / reopen / shutdown) | ✅ (Unix) |
| HTTP/2 | ❌ not yet |
| WebSocket proxying | ⚠️ partial |
| Dynamic modules | ❌ |