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.

FormDescription
scgi { ... }Enables SCGI and configures nested directives.
scgi <url: string> { ... }Enables SCGI and sets the backend URL directly.

backend

Nested directiveArgumentsDescriptionDefault
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
    }
}
Note
  • 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 Unavailable response.

environment

Nested directiveArgumentsDescriptionDefault
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"
    }
}
Note
  • Environment variables take precedence over any existing variables with the same name.
  • The Proxy header 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, and SERVER_ADMIN automatically.

Environment variables

Ferron automatically sets the following SCGI environment variables:

VariableDescription
SERVER_SOFTWAREAlways Ferron.
SERVER_NAMEServer hostname.
SERVER_ADDRLocal server address.
SERVER_PORTServer port.
REQUEST_METHODHTTP method.
REQUEST_URIOriginal request URI.
QUERY_STRINGQuery string (empty string if none).
PATH_INFOPath info extracted from the request.
SCRIPT_NAMEThe script path relative to the document root.
AUTH_TYPEAuthentication type from the Authorization header (e.g., Basic, Bearer).
REMOTE_USERAuthenticated username, if available.
SERVER_ADMINServer administrator email (from admin_email configuration).
HTTPSSet to on when the connection is encrypted.

Additional variables set by environment directives override any automatically set variables with the same name.

Tip

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:

HeaderSCGI environment variable
traceparentHTTP_TRACEPARENT
tracestateHTTP_TRACESTATE
baggageHTTP_BAGGAGE

This enables end-to-end distributed tracing with SCGI backend applications.

Info

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)LevelAttributes
SCGI service unavailableERRORupstream.address (string) — backend server URL

Metrics

MetricTypeAttributesDescription
ferron.scgi.requestsCounterNumber of SCGI requests processed
ferron.scgi.failuresCountererror.type ("service_unavailable"), ferron.scgi.backend_urlNumber of SCGI requests that failed before a backend response was returned
ferron.scgi.upstream.durationHistogramferron.scgi.backend_urlDuration 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
}