https://github.com/walf443/nginx-lint
A linter for nginx configuration files with WASM plugin support
https://github.com/walf443/nginx-lint
nginx
Last synced: 4 months ago
JSON representation
A linter for nginx configuration files with WASM plugin support
- Host: GitHub
- URL: https://github.com/walf443/nginx-lint
- Owner: walf443
- License: mit
- Created: 2026-02-07T04:17:54.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2026-02-16T03:30:39.000Z (4 months ago)
- Last Synced: 2026-02-16T11:19:33.453Z (4 months ago)
- Topics: nginx
- Language: Rust
- Homepage: https://walf443.github.io/nginx-lint/
- Size: 1.2 MB
- Stars: 26
- Watchers: 1
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# nginx-lint
[](LICENSE)
A linter for nginx configuration files with WASM plugin support, autofix, and a browser-based Web UI.
## Features
- **30+ built-in rules** covering security, best practices, style, syntax, and deprecation
- **Autofix** — automatically fix problems with `--fix`
- **WASM plugin system** — extend with custom rules written in Rust and compiled to WebAssembly
- **Web UI** — lint interactively in the browser with real-time feedback
- **Ignore comments** — suppress specific warnings with inline annotations
- **Configurable** — customize rules, severity, and options via `.nginx-lint.toml`
- **JSON output** — machine-readable output for CI integration
- **GitHub Actions integration** — inline PR annotations with `--format github-actions`
## Quick Start
You can also try it in the browser: [Demo](https://walf443.github.io/nginx-lint/)
```bash
# Lint a configuration file
nginx-lint /etc/nginx/nginx.conf
# Automatically fix problems
nginx-lint --fix /etc/nginx/nginx.conf
# Show why a rule exists
nginx-lint why server-tokens-enabled
# List all available rules
nginx-lint why --list
```
### Docker
```bash
# Lint a configuration file (replace TARGET_PATH with your config path)
TARGET_PATH=/etc/nginx/nginx.conf docker run --rm -v "$(dirname "$TARGET_PATH"):$(dirname "$TARGET_PATH"):ro" ghcr.io/walf443/nginx-lint:latest "$TARGET_PATH"
# Automatically fix problems (mount as read-write)
TARGET_PATH=/etc/nginx/nginx.conf docker run --rm -v "$(dirname "$TARGET_PATH"):$(dirname "$TARGET_PATH")" ghcr.io/walf443/nginx-lint:latest --fix "$TARGET_PATH"
```
## Usage
```
nginx-lint [OPTIONS] [FILE]...
nginx-lint
```
### Options
| Flag | Description |
|------|-------------|
| `-o, --format ` | Output format: `errorformat` (default), `json`, or `github-actions` |
| `--fix` | Automatically fix problems |
| `-c, --config ` | Path to configuration file |
| `--context ` | Parent context for partial configs (e.g., `http,server`) |
| `--plugins ` | Directory containing custom WASM plugins |
| `--color` / `--no-color` | Force or disable colored output |
| `--no-fail-on-warnings` | Only fail on errors, not warnings |
| `-v, --verbose` | Show verbose output |
| `--profile` | Show time spent per rule |
### Subcommands
**`config`** — Configuration file management
```bash
nginx-lint config init # Generate default .nginx-lint.toml
nginx-lint config init -o custom.toml # Custom output path
nginx-lint config validate # Validate configuration
```
**`why`** — Show detailed documentation for a rule
```bash
nginx-lint why server-tokens-enabled # Explain a rule
nginx-lint why --list # List all rules
```
## Configuration
Generate a default configuration file with:
```bash
nginx-lint config init
```
This creates `.nginx-lint.toml`:
```toml
[color]
ui = "auto" # "auto", "always", or "never"
error = "red"
warning = "yellow"
[rules.server-tokens-enabled]
enabled = true
[rules.indent]
indent_size = "auto" # or a number like 4
[rules.deprecated-ssl-protocol]
allowed_protocols = ["TLSv1.2", "TLSv1.3"]
# Support non-standard directives from extension modules
[rules.invalid-directive-context]
additional_contexts = { server = ["rtmp"], upstream = ["rtmp"] }
[parser]
block_directives = ["rtmp", "application"]
```
## Rules
See the [rules list](https://walf443.github.io/nginx-lint/rules.html) for all available rules, or run `nginx-lint why --list` locally.
## Ignore Comments
Suppress warnings using `nginx-lint:ignore` comments. Both a rule name and a reason are required.
**Comment on the line before:**
```nginx
# nginx-lint:ignore server-tokens-enabled required by monitoring system
server_tokens on;
```
**Inline comment:**
```nginx
server_tokens on; # nginx-lint:ignore server-tokens-enabled required by monitoring system
```
### Context Comments
When linting partial configuration files (e.g., included snippets), specify the parent context:
```nginx
# nginx-lint:context http,server
location /api {
proxy_pass http://backend;
}
```
This is equivalent to `--context http,server` on the command line.
## Include Resolution
nginx-lint automatically follows `include` directives and lints the included files as well. Both absolute paths and glob patterns (e.g. `include /etc/nginx/conf.d/*.conf;`) are supported.
### Path Mapping
In production, nginx configs often include files from a directory that is populated at runtime via symlinks (e.g. `sites-enabled/`), while the actual source files live elsewhere (e.g. `sites-available/`). You can configure path mappings in `.nginx-lint.toml` so that nginx-lint reads from the correct location:
```toml
[[include.path_map]]
from = "sites-enabled"
to = "sites-available"
```
With this configuration, an `include sites-enabled/*.conf;` directive will be resolved as `sites-available/*.conf` during linting.
Key behaviors:
- **Component-level matching** — `from` is matched against exact path segments, so `sites-enabled` will not match `asites-enabled` or `sites-enabled-old`.
- **Multi-segment values** — `from = "nginx/sites-enabled"` matches consecutive path components.
- **Chained application** — Multiple `[[include.path_map]]` entries are applied in declaration order, with each mapping receiving the output of the previous one.
```toml
# Chained example: sites-enabled → sites-available → conf
[[include.path_map]]
from = "sites-enabled"
to = "sites-available"
[[include.path_map]]
from = "sites-available"
to = "conf"
```
## Web UI
Try the Web UI online without installation: [Demo](https://walf443.github.io/nginx-lint/)
Start the browser-based linting interface locally:
```bash
nginx-lint web --open
```
The Web UI provides:
- Real-time linting as you type
- Interactive fix buttons for each issue
- "Fix All" to apply all fixes at once
- Rule documentation with bad/good examples
- In-browser configuration editing
- Runs entirely client-side via WebAssembly
## GitHub Actions
You can use [nginx-lint-action](https://github.com/walf443/nginx-lint-action) to run nginx-lint in your GitHub Actions workflow with inline PR annotations:
```yaml
- uses: walf443/nginx-lint-action@v1
with:
files: /etc/nginx/nginx.conf
```
Alternatively, use `--format github-actions` directly to produce workflow commands:
```bash
nginx-lint --format github-actions /etc/nginx/nginx.conf
```
## Custom Plugins
Load custom WASM plugins from a directory:
```bash
nginx-lint --plugins ./my-plugins /etc/nginx/nginx.conf
```
Each `.wasm` file in the directory is loaded as a plugin. See the `plugins/builtin/` directory for examples of how to write plugins using the `nginx-lint-plugin` SDK.
## Installation
### From source
```bash
# Default build (CLI + builtin plugins)
cargo install --path .
# With web server support
cargo install --path . --features web-server
# Build with embedded WASM plugins instead of native (requires WASM toolchain)
make build-plugins
cargo install --path . --no-default-features --features cli,wasm-builtin-plugins
```
### Cargo features
| Feature | Description |
|---------|-------------|
| `cli` | Command-line interface (default) |
| `native-builtin-plugins` | Compile builtin plugins as native Rust (default) |
| `wasm-builtin-plugins` | Embed builtin WASM plugins in the binary (requires `make build-plugins`) |
| `plugins` | Support loading external WASM plugins |
| `web-server` | Built-in web server for browser UI |
| `wasm` | WebAssembly target support |
## License
[MIT](LICENSE)