Configuration: syntax and file structure

This page covers the Ferron configuration file format, how blocks and directives are structured, and how configuration is resolved at runtime.

Ferron configuration files

Ferron uses .conf files parsed by the config-ferronconf adapter. A configuration file is made of top-level statements that define global blocks, host blocks, matchers, and snippets.

include "shared.conf"

{
    runtime {
        io_uring true
    }

    tcp {
        listen "::"
    }
}

match api_request {
    request.uri.path ~ "/api"
    request.method in "GET,POST"
}

snippet common_http {
    http {
        protocols h1 h2
    }
}

example.com {
    use common_http

    tls {
        provider manual
        cert "{{env.TLS_CERT}}"
        key "{{env.TLS_KEY}}"
    }
}

Top-level statements

A configuration file can contain the following at the top level:

  • Global blocks{ ... } for server-wide settings
  • Host blocks<host-pattern> { ... } for virtual host configuration
  • Match blocksmatch <name> { ... } for reusable conditional matchers
  • Snippet blockssnippet <name> { ... } for reusable directive groups
  • Include directivesinclude "path.conf" to load additional configuration files

Value types

Ferron configuration supports these value types:

  • Strings — bare (example.com) or quoted ("example.com")
  • Integers80, 443, 1000
  • Floats3.14
  • Booleanstrue, false
  • Interpolated strings{{env.TLS_CERT}} reads from environment variables
  • Duration strings30m, 1h, 90s, 1d

Flags (boolean directives)

Several directives accept boolean values. For convenience, these can be written as flags with no arguments, which is equivalent to true:

# These are equivalent:
directory_listing
directory_listing true

# To explicitly disable, use false:
directory_listing false

This shorthand is useful for simple on/off toggles where the intent is clear. The following directives support flag syntax: abort, compressed, precompressed, etag, directory_listing, trailing_slash_redirect, url_sanitize, keepalive, http2, http2_only, intercept_errors, no_verification, lb_health_check, lb_retry_connection, on_demand, client_auth, and others.

Duration strings

Several directives accept duration values. The following formats are supported:

SuffixUnitExampleResult
h or HHours12h, 1H12 hours
m or MMinutes30m, 30M30 minutes
s or SSeconds90s, 90S90 seconds
d or DDays1d, 1D1 day
(none)Hours (default)1212 hours

Plain numbers without a suffix are treated as hours for backward compatibility.

Comments start with #.

Host block syntax

Host blocks are top-level only. Supported selectors include:

  • example.com — hostname-based virtual host
  • *.example.com — wildcard hostname
  • 127.0.0.1 — IP-based virtual host
  • [2001:db8::1] — IPv6 address
  • http example.com — explicit protocol
  • http example.com:8080 — explicit protocol and port
  • tcp *:5432 — TCP listener

Current defaults:

  • If the protocol is omitted, it defaults to http.
  • For HTTP host blocks, if the port is omitted, Ferron treats it as port 80.

When a hostname is specified (e.g. example.com) and no explicit port is given, Ferron starts two listeners — one on the default HTTP port (80) and one on the default HTTPS port (443) with automatic ACME TLS. See ACME automatic TLS for details.

Includes and snippets

  • include "path.conf" at the top level loads another config file relative to the current file.
  • snippet <name> { ... } defines a reusable block of directives.
  • use <snippet-name> inside a block expands that snippet in place.

Notes:

  • Top-level file includes and snippet expansion are different features.
  • Include cycles and snippet cycles are rejected.
  • Snippets can be reused across multiple host blocks.

Resolution model

Configuration is resolved in layers:

  1. Global configuration from { ... } is used for startup and runtime settings.
  2. An HTTP host block is selected by local IP and hostname.
  3. Matching location blocks are layered in.
  4. Matching if and if_not blocks are layered in.

Important behavior:

  • location is prefix-based. /api matches /api and /api/users.
  • More specific locations win over less specific ones.
  • All expressions inside a match block are combined with AND semantics.
  • Duplicate location, if, if_not, and handle_error blocks with the same selector are merged during preparation.

Inheritance and override behavior

Ferron applies inheritance by block context:

  • Location blocks inherit parent directives unless the child block defines directives with the same name.
  • When a child block defines a directive with the same name as one in the parent, the child’s directives take precedence in that block.
  • For conditional branches, it is often clearer to explicitly use shared snippets inside each if/if_not branch.

Hot-reload support

Ferron .conf configuration files support hot-reload. When the file changes, Ferron detects the update and reloads the configuration gracefully. The ConfigurationWatcher monitors the file for modifications.

To enable hot reloading, specify a watch configuration adapter parameter:

ferron run --config-params 'watch=1;file=ferron.conf' --config-adapter ferronconf

Notes

  • Where validation and runtime behavior differ, the directive pages call that out explicitly.
  • Duration strings accept suffixes like 30m, 1h, 90s, 1d. Plain numbers without a suffix are treated as hours.
  • Boolean directives can be written as bare flags (equivalent to true), or explicitly as true or false.

See also