Configuration compatibility
xin reads the configuration language you already use. This page is the honest edge of that claim: what runs, what differs, and what will stop the server from starting.
Do not read this page to find out whether your config works. Run it instead — the answer is specific to your file and takes one command:
xind -t -c /etc/nginx/nginx.conf Three outcomes, no fourth
| Outcome | What it means |
|---|---|
| Runs | xin reproduces the behaviour, including the parts of it that surprise people. |
| Runs, stated | Behaviour differs in a known, catalogued way. Reported at load with file and line; the server still starts. |
| Refuses | xin cannot honour the directive, so it does not start. The error names the file, the line and the reason. |
Nothing is accepted, ignored and left unmentioned. A directive that would quietly do nothing is a startup failure instead — you find it in staging, not in an incident review.
Supported
| Area | Directives |
|---|---|
| Core structure | http, server, location, upstream, include (with globs), default_type, worker_processes, worker_connections |
| Request routing | listen (addr, port, ssl, default_server, reuseport, backlog), server_name (exact, wildcard, regex) with nginx's matching order, location with nginx's precedence rules |
| Content | root, alias, index, try_files, autoindex, error_page, return, rewrite, set, break, if (subset) |
| Static serving | Conditional requests, byte ranges including multipart, sendfile, if_modified_since, expires |
| Proxying | proxy_pass over http:// and https://, proxy_set_header, proxy_http_version, the proxy_ssl_* set with certificate pinning, proxy_read/connect/send_timeout, proxy_next_upstream, proxy_buffering, proxy_request_buffering, proxy_limit_rate, proxy_intercept_errors, proxy_ignore_headers, proxy_cookie_path/domain/flags |
| Upstreams | upstream blocks with server, weight, max_fails, fail_timeout, backup, down; keepalive; least_conn, ip_hash, hash, random [two]; passive health checks |
| TLS | ssl_certificate, ssl_certificate_key, ssl_protocols, ssl_ciphers, SNI, dual certificates, ALPN; HTTP/1.1 and HTTP/2 |
| Filters & vars | gzip with gzip_types/min_length/comp_level, map, geo, split_clients, real_ip, sub_filter |
| Access control | allow, deny, auth_basic, auth_basic_user_file, auth_request, satisfy, limit_except, valid_referers, secure_link |
| Limits | limit_req + limit_req_zone, limit_conn + limit_conn_zone + limit_conn_status, limit_rate, limit_rate_after, client_max_body_size, client_body/header_timeout, keepalive_timeout, keepalive_requests |
| Logging | access_log, error_log, log_format with the full variable set |
| Other | add_header, mirror, X-Accel-Redirect, proxy_cache (in memory) |
Refused at load
Each of these is a named startup error, never a silent skip. A build without a feature says so at startup rather than failing at request time.
| Not supported | Why |
|---|---|
| mail and stream modules | Out of scope. xin is an HTTP server; a TCP/UDP proxy is a different product. |
| uwsgi and SCGI | Not implemented. FastCGI is. |
| SSI | Not implemented. |
| Lua and njs scripting | Not implemented, and not planned. |
| Third-party C modules | There is no module ABI, and there will not be one — that is the point of a single memory-safe binary. |
| fastcgi_cache, fastcgi_next_upstream | The rest of FastCGI works; these two are refused rather than silently ignored. |
| proxy_store, proxy_store_access | There is no filesystem-backed passthrough cache to write to, so a config relying on it would start and silently populate nothing. |
| ssl_ciphers OpenSSL group tokens (HIGH, MEDIUM…) | A cipher policy that is approximated is a config that lies. Name the suites explicitly and it loads. |
Compatibility means the bugs too
Where the documented behaviour and the actual behaviour of nginx disagree, xin follows the actual behaviour, because that is what your config was written against. Some examples that surprise people:
-
if_modified_sincedefaults toexact: a request date newer than the file gets the whole entity, not a 304. Implementing the intuitive comparison would serve a stale body. -
locationselection is not first-match-wins:=beats^~beats regexes-in-order beats longest prefix, independent of the order you wrote them in. -
gzip oncompresses exactly 200, 403 and 404 — not 201, not 301, not your 500 page. -
proxy_ssl_verifydefaults tooff, soproxy_pass https://…is encrypted but unauthenticated unless you asked for verification.
One place xin deliberately follows intent instead: error_log off;.
There is no off keyword for error_log — nginx
treats it as a filename and creates a file called off. xin
writes nothing and creates no such file.