vane 0.9.0

A flow-based reverse proxy with multi-layer routing and programmable pipelines.
---
title: Configuration
description: Environment and file-based configuration management.
icon: Settings
---

import { Steps, Step } from 'fumadocs-ui/components/steps';

Vane uses a dual-layer configuration strategy: **Environment Variables** for static startup parameters (like ports and paths) and **File-Based Configuration** for dynamic, hot-swappable resources (like upstream nodes and protocol routes).

The `src/common/config` module provides the tooling to load, parse, and validate these configurations safely.

## Environment Variables

The `env_loader.rs` module handles basic string retrieval from the process environment.

- **Defaults**: All retrievals support a default fallback value.
- **Utility**: Includes helpers for boolean parsing and numeric validation.

```rust
use crate::common::config::env_loader;

// If "PORT" is not set, returns "3333"
let port = env_loader::get_env("PORT", "3333".to_string());
```

## File Loading System

The core complexity lies in `loader.rs` and `file_loader.rs`, which implement a robust, multi-format configuration loading pipeline.

### Supported Formats

Vane supports the following formats, automatically detecting them by extension in this order:

1.  `toml`
2.  `yaml` / `yml`
3.  `json`

### The Loading Pipeline

When `load_file<T>(path)` is called, the following security and validation steps occur:

<Steps>
<Step>

### Path Resolution & Security Check

The loader resolves the absolute path of the target file.
**Crucially**, it verifies that the resolved path is strictly within the `CONFIG_DIR`.

<Mermaid
	chart="
graph LR
    Input[Input Path] --> Resolve[Abs Path]
    Resolve --> Check{Inside CONFIG_DIR?}
    Check -- Yes --> Safe[Proceed]
    Check -- No --> Deny[Return None]
"
/>

</Step>
<Step>

### Format Detection & Parsing

The file extension determines the parser (`serde_json`, `serde_yaml`, or `toml`). The content is deserialized into the generic type `T`.

<Mermaid
	chart="
graph LR
    File[File Content] --> Ext{Extension?}
    Ext -- .toml --> TOML[Toml Parser]
    Ext -- .yaml --> YAML[Yaml Parser]
    Ext -- .json --> JSON[Json Parser]
    TOML & YAML & JSON --> Struct[Struct T]
"
/>

</Step>
<Step>

### Pre-Processing

If type `T` implements the `PreProcess` trait, the `pre_process()` hook is called. This allows configurations to mutate themselves immediately after loading (e.g., injecting context like the filename).

<Mermaid
	chart="
graph LR
    Struct[Struct T] --> Hook[pre_process]
    Hook --> Mutated[Mutated T]
"
/>

</Step>
<Step>

### Validation

Finally, the `validate()` method (from the `validator` crate) is executed. If validation fails, the loader returns `None` and logs a detailed error.

<Mermaid
	chart="
graph LR
    Mutated[Mutated T] --> Valid{validate}
    Valid -- Ok --> Result[Return Some<T>]
    Valid -- Err --> Log[Log Errors]
    Log --> None[Return None]
"
/>

</Step>
</Steps>

<Callout type="warn" title="Conflict Detection">
	If multiple files with the same base name exist (e.g., `nodes.toml` and `nodes.json`), the loader
	will detect this ambiguity, log a warning, and ignore the duplicates to prevent deterministic
	confusion.
</Callout>

## Initialization

The `file_loader` module also handles the "scaffolding" of the configuration directory. Functions like `init_config_files` ensure that the required directory structure exists on startup, creating default files if they are missing. This improves the "first-run" experience.