Ferrit Explore
中文·繁體·EN·日本語 Sign in Register
cielxl / veld / docs / USER_MANUAL.md
# 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 | ❌ |