| Crates.io | env-schema |
| lib.rs | env-schema |
| version | 0.1.0 |
| created_at | 2026-01-04 21:30:44.469289+00 |
| updated_at | 2026-01-04 21:30:44.469289+00 |
| description | Environment variable schema validation and management for Rust |
| homepage | |
| repository | https://github.com/eladbash/env-schema |
| max_upload_size | |
| id | 2022517 |
| size | 309,824 |
Environment variable schema validation and management for Rust
env-schema provides a declarative approach to managing environment variables in Rust applications. Define your configuration schema once, and get validation, documentation generation, and type-safe loading for free.
Three core benefits:
📋 Contract: Your schema is the single source of truth. Environment variables are validated against the schema at startup, catching configuration errors early.
📚 Documentation: Automatically generate .env.example files and Markdown documentation from your schema. Keep your docs in sync with your code.
🛡️ Strict Mode: Optionally enforce that only known environment variables are present, preventing typos and accidental configuration drift.
Cargo.toml:[dependencies]
env-schema = "0.1.0"
env-schema-derive = "0.1.0"
use env_schema::prelude::*;
use env_schema::resolve::LoadMode;
use env_schema::secret::Secret;
use env_schema_derive::EnvSchema;
#[derive(EnvSchema, Debug)]
struct AppConfig {
/// Database connection URL
#[env(required, secret, example = "postgres://user:password@localhost:5432/mydb")]
database_url: Secret<String>,
/// Server port number
#[env(default = "3000", range(min = 1.0, max = 65535.0))]
port: u16,
/// Application environment
#[env(default = "development", values = ["development", "staging", "production"])]
environment: String,
}
fn main() -> Result<()> {
let config = AppConfig::load(LoadMode::Lenient)?;
println!("Database: {}", config.database_url.expose());
println!("Port: {}", config.port);
println!("Environment: {}", config.environment);
Ok(())
}
String, u16, u32, u64, i32, i64, bool, Option<T>, and custom types via FromStrSecret<T> redacts sensitive values in Debug and Display output.env.example files: Auto-generate example environment filesSee INTEGRATIONS.md for:
dotenv, serde, config-rs, tokio, clap)When validation fails, env-schema provides clear, actionable error messages:
Configuration validation failed with 3 error(s):
1. Missing required environment variable: `DATABASE_URL`
2. Value for `PORT` is out of range: `99999` (expected 1 to 65535)
3. Value for `ENVIRONMENT` does not match pattern `^(dev|staging|prod)$`: `invalid`
Errors are collected and reported together, so you can fix all issues in one pass.
Generate documentation from your schema:
use env_schema_derive::EnvSchema;
#[derive(EnvSchema)]
struct AppConfig {
#[env(required, secret, example = "postgres://localhost/db")]
database_url: Secret<String>,
#[env(default = "3000", doc = "Server port")]
port: u16,
}
fn main() {
let schema = AppConfig::schema();
// Generate .env.example
let env_example = schema.render_env_example();
std::fs::write(".env.example", env_example).unwrap();
// Generate Markdown documentation
let docs = schema.render_docs_md();
std::fs::write("CONFIG.md", docs).unwrap();
}
.env.example Output# Database connection URL
# Required
DATABASE_URL=<secret>
# Server port
PORT=3000
# Configuration
## How to Use
Set environment variables before running the application...
## Environment Variables
| Key | Required | Default | Example | Description | Constraints |
|-----|----------|---------|---------|-------------|-------------|
| `DATABASE_URL` | **Yes** | — | `<secret>` | Database connection URL | — |
| `PORT` | No | `3000` | — | Server port | Range: 1 to 65535 |
Secret<T>The Secret<T> wrapper type prevents accidental exposure of sensitive values:
use env_schema::secret::Secret;
let api_key = Secret("my-secret-key".to_string());
// Safe: redacts the value
println!("{:?}", api_key); // prints: <redacted>
println!("{}", api_key); // prints: <redacted>
// Explicit access when needed
let actual_key = api_key.expose();
⚠️ Important:
Secret<T>only prevents accidental logging viaDebugandDisplay. The value is still stored in memory. For production secrets, use proper secret management systems and never commit secrets to version control.
Enable optional features in Cargo.toml:
[dependencies]
env-schema = { version = "0.1.0", features = ["json", "url", "humantime"] }
yaml (optional): Enables loading schemas from YAML files. Allows tools like envctl to consume schemas without needing Rust derive macros.
json (optional): Enables JSON error report rendering via report::render_json(). Useful for programmatic consumption of error reports in structured format.
url (optional): Enables parsing of Url types from the url crate. Allows environment variables to be parsed directly into url::Url types with validation.
humantime (optional): Enables parsing of Duration types using human-readable strings. Supports formats like "5s", "10m", "1h", "2d", or combinations like "1h30m15s".
You can load a schema from a YAML file or string, which is useful for tools that need to consume schemas without Rust code.
Add the yaml feature to your Cargo.toml:
[dependencies]
env-schema = { version = "0.1.0", features = ["yaml"] }
A YAML schema can be defined with a top-level fields: array (preferred) or as a direct array:
fields:
- key: "DB_URL"
required: true
secret: true
doc: "Postgres connection string"
example: "postgres://user:pass@host:5432/db"
default: null
aliases: ["DATABASE_URL"]
deprecated: false
range:
min: 1
max: 200
values: null
regex: null
- key: "PORT"
required: false
default: "3000"
doc: "Server port"
range:
min: 1
max: 65535
use env_schema::schema::Schema;
// Load from a file
let schema = Schema::from_yaml_file("schema.yaml")?;
// Or load from a string
let yaml = r#"
fields:
- key: "DB_URL"
required: true
secret: true
"#;
let schema = Schema::from_yaml_str(yaml)?;
// Use the schema as normal
let config = schema.load_map(LoadMode::Strict)?;
key (required): The environment variable name (must be non-empty)required (default: false): Whether the variable must be presentsecret (default: false): Whether the variable contains sensitive datadoc (optional): Human-readable documentationexample (optional): Example valuedefault (optional): Default value (null means no default)aliases (optional): Array of alternative variable namesdeprecated (default: false): Whether the field is deprecateddeprecated_message (optional): Deprecation message (auto-generated if deprecated: true and message is empty)range (optional): Numeric range constraint with min and maxvalues (optional): Array of allowed values (enum constraint)regex (optional): Regular expression pattern constraintThe YAML loader performs comprehensive validation:
min <= maxAll validation errors are aggregated and returned together for easy debugging.
See examples/schema.yaml for a complete example.
See examples/web_service.rs for a complete example with:
Licensed under the MIT license (LICENSE-MIT)