Configuration: SCGI support
This page documents the scgi directive for configuring Ferron’s SCGI (Simple Common Gateway Interface) support. SCGI is a protocol for interfacing external application servers with web servers, similar to CGI but with binary framing for better performance.
scgi
example.com {
scgi {
backend tcp://127.0.0.1:4000
environment "APP_ENV" "production"
}
}The scgi directive enables SCGI protocol support. When specified, Ferron will forward requests to the configured SCGI backend using the SCGI protocol instead of spawning local processes.
| Form | Description |
|---|---|
scgi { ... } | Enables SCGI and configures nested directives. |
scgi <url: string> { ... } | Enables SCGI and sets the backend URL directly. |
backend
| Nested directive | Arguments | Description | Default |
|---|---|---|---|
backend | <url: string> | This directive specifies the SCGI backend server URL. Supports TCP URLs (tcp://host:port) and Unix socket URLs (unix:///path/to/socket). | — |
Configuration example:
example.com {
scgi {
backend tcp://127.0.0.1:4000
}
}Configuration example with Unix socket:
example.com {
scgi {
backend unix:///var/run/app.sock
}
}- TCP URLs must include both host and port (e.g.,
tcp://127.0.0.1:4000). - Unix socket paths must be absolute paths.
- When a connection failure occurs (connection refused, host unreachable, etc.), Ferron logs an error and returns a
503 Service Unavailableresponse.
environment
| Nested directive | Arguments | Description | Default |
|---|---|---|---|
environment | <name: string> <value: string> | This directive sets an SCGI environment variable passed to the backend server. Values are resolved with the same interpolation syntax as other directives. This directive can be specified multiple times. | — |
Configuration example:
example.com {
scgi {
backend tcp://127.0.0.1:4000
environment "APP_ENV" "production"
environment "APP_SECRET" "{{env.APP_SECRET}}"
environment "RUBY_VERSION" "3.3"
}
}- Environment variables take precedence over any existing variables with the same name.
- The
Proxyheader is automatically removed from the request to prevent the httpoxy vulnerability. - Ferron always sets
SERVER_SOFTWARE,SERVER_NAME,SERVER_ADDR,SERVER_PORT,REQUEST_URI,QUERY_STRING,PATH_INFO,SCRIPT_NAME,AUTH_TYPE,REMOTE_USER, andSERVER_ADMINautomatically.
Environment variables
Ferron automatically sets the following SCGI environment variables:
| Variable | Description |
|---|---|
SERVER_SOFTWARE | Always Ferron. |
SERVER_NAME | Server hostname. |
SERVER_ADDR | Local server address. |
SERVER_PORT | Server port. |
REQUEST_METHOD | HTTP method. |
REQUEST_URI | Original request URI. |
QUERY_STRING | Query string (empty string if none). |
PATH_INFO | Path info extracted from the request. |
SCRIPT_NAME | The script path relative to the document root. |
AUTH_TYPE | Authentication type from the Authorization header (e.g., Basic, Bearer). |
REMOTE_USER | Authenticated username, if available. |
SERVER_ADMIN | Server administrator email (from admin_email configuration). |
HTTPS | Set to on when the connection is encrypted. |
Additional variables set by environment directives override any automatically set variables with the same name.
For authentication integration, SCGI scripts receive REMOTE_USER and AUTH_TYPE only when used alongside a module like http-basicauth that sets ctx.auth_user.
Authentication
When used alongside an authentication module (e.g., http-basicauth), Ferron automatically populates the AUTH_TYPE and REMOTE_USER environment variables in the SCGI request. The authentication type is extracted from the Authorization header (e.g., Basic or Bearer).
Trace context injection
When a trace context exists for the request, Ferron automatically injects W3C Trace Context headers (traceparent, tracestate, and baggage) into the SCGI request. These headers are mapped to standard CGI environment variables:
| Header | SCGI environment variable |
|---|---|
traceparent | HTTP_TRACEPARENT |
tracestate | HTTP_TRACESTATE |
baggage | HTTP_BAGGAGE |
This enables end-to-end distributed tracing with SCGI backend applications.
No per-module configuration is needed. Trace context injection is controlled globally by whether a trace context exists — see Tracing configuration for details on enabling trace generation and sampling.
Observability
Logs
ERROR: logged when a connection to the SCGI backend fails. The message includes the connection error details.
Structured logs
| Description (summary) | Level | Attributes |
|---|---|---|
| SCGI service unavailable | ERROR | upstream.address (string) — backend server URL |
Metrics
| Metric | Type | Attributes | Description |
|---|---|---|---|
ferron.scgi.requests | Counter | — | Number of SCGI requests processed |
ferron.scgi.failures | Counter | error.type ("service_unavailable"), ferron.scgi.backend_url | Number of SCGI requests that failed before a backend response was returned |
ferron.scgi.upstream.duration | Histogram | ferron.scgi.backend_url | Duration of SCGI upstream request processing |
Examples
Basic SCGI backend
example.com {
scgi tcp://127.0.0.1:4000
}SCGI with Unix socket
example.com {
scgi unix:///var/run/app.sock
}SCGI with environment variables
example.com {
scgi {
backend "tcp://127.0.0.1:4000"
environment "APP_ENV" "production"
environment "APP_SECRET" "{{env.APP_SECRET}}"
environment "RUBY_VERSION" "3.3"
}
}SCGI with authentication
example.com {
root /var/www/html
basic_auth {
users {
admin "$argon2id$v=19$m=19456,t=2,p=1$..."
}
}
scgi tcp://127.0.0.1:4000
}