Configuration formatting
This page documents the ferron-fmt tool, a formatter for Ferron configuration files. It formats .conf files with configurable indentation, quote style, and other styling options.
The idiomatic Ferron 3 configuration style uses bare strings without quotes (when possible), 4-space indentation, and bare boolean flags. The ferron-fmt formatter also supports raw string literals for regex patterns and defaults to this style.
What it does#
ferron-fmt parses a Ferron configuration file and rewrites it with consistent formatting. It handles:
- Indentation: configurable width and style (spaces or tabs)
- Quote style: auto (bare when possible, quoted when necessary), always double-quoted, or always bare
- Blank lines: normalization with a configurable maximum consecutive blank lines
- Trailing newline: optional trailing newline
- Directive sorting: optional alphabetical sorting of directives within blocks
- Comment preservation: the formatter preserves inline and trailing comments
- Quoting normalization: bare strings when possible, double-quoted when necessary (for example, values that would be ambiguous)
- Raw string preservation: the formatter preserves
r"..."syntax for strings that were originally raw - Line continuation preservation: the formatter preserves
\at end of line at the same position
Use this tool to make sure formatting is consistent across multiple Ferron configuration files.
The formatter is idempotent (meaning running it multiple times on the same file produces identical output).
Installation#
All Ferron distributions include ferron-fmt alongside the main server binary. See Installation for details.
Usage#
Format a file to stdout#
ferron-fmt ferron.confFormat a file in place#
ferron-fmt -i ferron.confWrite to a specific file#
ferron-fmt -o formatted.conf ferron.confRead from stdin#
cat ferron.conf | ferron-fmtCheck if a file is already formatted#
ferron-fmt --check ferron.confExits with code 0 if the file is already formatted, 1 if not. Useful for CI:
ferron-fmt --check ferron.conf && echo "Formatted" || echo "Needs formatting"Options#
| Option | Default | Description |
|---|---|---|
--indent-width <n> | 4 | Number of spaces per indentation level |
--indent-style <style> | spaces | Indentation style: spaces or tabs |
--quote-style <style> | auto | Quote style: auto, always-double, or always-bare |
--no-normalize-quotes | none | Preserve original quoting style instead of normalizing |
--max-blank-lines <n> | 2 | Maximum number of consecutive blank lines to preserve |
--no-trailing-newline | none | Do not add a trailing newline at the end of the file |
--sort-directives | none | Sort directives alphabetically within blocks |
--check | none | Check if input is already formatted (exit 1 if not) |
-i, --in-place | none | Edit file in place |
-o, --output <file> | none | Write output to file instead of stdout |
Indentation#
Spaces (default)#
ferron-fmt --indent-style spaces --indent-width 4 ferron.confexample.com {
root /var/www/html
tls {
provider manual
cert /etc/ssl/cert.pem
key /etc/ssl/key.pem
}
}Tabs#
ferron-fmt --indent-style tabs ferron.confexample.com {
root /var/www/html
tls {
provider manual
cert /etc/ssl/cert.pem
key /etc/ssl/key.pem
}
}Quote style#
Auto (default)#
Bare strings when possible, double-quoted when necessary (this produces idiomatic Ferron 3 configuration style):
ferron-fmt --quote-style auto ferron.confexample.com {
root /var/www/html
tls {
provider manual
cert /etc/ssl/cert.pem
key /etc/ssl/key.pem
}
}Values that require quoting (would be ambiguous):
example.com {
root "/var/www/html"
tls {
provider "manual"
cert "/etc/ssl/cert.pem"
}
}Always double-quoted#
ferron-fmt --quote-style always-double ferron.confexample.com {
root "/var/www/html"
tls {
provider "manual"
cert "/etc/ssl/cert.pem"
key "/etc/ssl/key.pem"
}
}Always bare#
ferron-fmt --quote-style always-bare ferron.confexample.com {
root /var/www/html
tls {
provider manual
cert /etc/ssl/cert.pem
key /etc/ssl/key.pem
}
}always-bare produces a parse error if the formatter cannot represent a value as a bare string. For example, values containing spaces or special characters cause this error.
Preserving original quoting#
By default, ferron-fmt normalizes quoting according to the configured quote style. Use --no-normalize-quotes to preserve the original quoting:
ferron-fmt --no-normalize-quotes ferron.confThis is useful when you want consistent indentation but do not want to change the quoting style.
Trailing newline#
By default, ferron-fmt adds a trailing newline at the end of the file:
ferron-fmt --no-trailing-newline ferron.confSorting directives#
By default, directives are output in the order they appear in the source. Use --sort-directives to sort them alphabetically:
ferron-fmt --sort-directives ferron.confexample.com {
root /var/www/html
tls {
provider manual
cert /etc/ssl/cert.pem
key /etc/ssl/key.pem
}
# Directives are sorted alphabetically:
# compress > directory_listing > root > tls
}Blank lines#
ferron-fmt preserves blank lines between directives up to the configured maximum (default: 2):
ferron-fmt --max-blank-lines 1 ferron.confThis collapses consecutive blank lines beyond the limit.
Raw strings#
The formatter preserves raw string syntax (r"...") for strings that were originally written as raw strings in the input. Raw strings are output with no escape processing, making them ideal for regex patterns:
match api_request {
request.uri.path ~ r"^/api/v1(?:/|$)"
}Running the formatter on this input keeps the r"..." syntax intact. Regular quoted strings ("...") are not converted to raw strings.
Raw strings do not support interpolation. The formatter does not convert interpolated strings to raw strings.
Line continuations#
The formatter preserves line continuations (\ at end of line) that were present in the original input. This is useful for splitting long directives across multiple lines:
example.com {
# This is just an example directive
example_proxy http://localhost:3000 \
http://localhost:3001
}After formatting, the formatter preserves the continuation at the same position. Line continuations with trailing comments are also preserved:
example.com {
# This is just an example directive
example_proxy http://localhost:3000 \ # first backend
http://localhost:3001
}Line continuations are only preserved when the formatter reads from a file or stdin. When formatting a pre-parsed AST directly (programmatic API), continuations are not available and the output uses single-line values.