serviceconf
Environment variable configuration with file-based secrets support
serviceconf provides a declarative API for loading configuration from environment
variables with native support for file-based secrets (Kubernetes Secrets, Docker Secrets).
The primary feature that distinguishes this library from other environment variable
configuration libraries is the #[conf(from_file)] attribute, which allows reading
secrets from files while falling back to direct environment variables for local development.
Features
- File-based secrets: Read secrets from Kubernetes/Docker mounted files
- Declarative: Automatic implementation with
#[derive(ServiceConf)] - Type-safe: Compile-time type checking
- Default values: Support for
Defaulttrait and explicit values - Custom deserializers: Support for JSON, TOML, or custom parsing functions
Quick Start
use ServiceConf;
let config = from_env.unwrap;
println!;
Local development (direct environment variable):
Production (Kubernetes/Docker with file-based secret):
Key Feature: File-based Secrets
The #[conf(from_file)] attribute allows reading secrets from files mounted by
Kubernetes or Docker, avoiding the security risks of exposing secrets directly in
environment variables.
Why file-based secrets?
- ✅ More secure: Secrets stored in files, not environment variables (which can leak in logs, process lists, etc.)
- ✅ Kubernetes native: Works seamlessly with Kubernetes Secrets mounting
- ✅ Docker Secrets: Direct support for Docker Swarm secrets
- ✅ Flexible: Falls back to direct environment variables for local development
Loading priority:
- Direct env var (
API_KEY) - for local development - File path from env var (
API_KEY_FILE) - for production
Kubernetes Secret Example
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
stringData:
api-key: "prod-api-key-123"
db-password: "secure-password"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myservice
spec:
template:
spec:
containers:
- name: app
image: myservice:latest
env:
- name: API_KEY_FILE
value: /etc/secrets/api-key
- name: DATABASE_PASSWORD_FILE
value: /etc/secrets/db-password
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: app-secrets
items:
- key: api-key
path: api-key
- key: db-password
path: db-password
With this Kubernetes configuration, your Rust application can simply use:
use ServiceConf;
Value Parsing
Default (using FromStr):
- Strings:
DATABASE_URL=postgres://localhost/db - Numbers:
MAX_CONNECTIONS=42 - Booleans:
DEBUG=true
Custom deserializers - specify with #[conf(deserializer = "function")]:
- JSON:
#[conf(deserializer = "serde_json::from_str")] - TOML:
#[conf(deserializer = "toml::from_str")] - Custom: Define your own deserializer function
Attribute Reference
Struct-level Attributes
#[conf(prefix = "PREFIX_")]
Add a prefix to all environment variable names in the struct.
use ServiceConf;
Environment variables:
Field-level Attributes
#[conf(from_file)] - File-based Secrets
Load from {VAR_NAME}_FILE in addition to the environment variable.
This is the primary feature of serviceconf for handling file-based secrets
in Kubernetes and Docker environments.
use ServiceConf;
#[conf(name = "CUSTOM_NAME")]
Specify an environment variable name different from the field name.
use ServiceConf;
#[conf(default)]
Use Default::default() if the environment variable is not set.
use ServiceConf;
#[conf(default = value)]
Specify an explicit default value when the environment variable is not set.
use ServiceConf;
#[conf(deserializer = "function")]
Use a custom deserializer function for complex types or custom parsing logic.
The deserializer function must have the signature:
Example with JSON:
use ServiceConf;
Environment variable:
Example with custom function:
use ServiceConf;
// Custom comma-separated parser
Environment variable:
Optional Fields
Use Option<T> for optional fields. Returns None if the environment variable is not set.
use ServiceConf;
Type Behavior
| Type | When Env Var Missing | When Env Var Set |
|---|---|---|
T (no attribute) |
Error | Parsed with FromStr |
T + #[conf(default)] |
Default::default() |
Parsed with FromStr |
T + #[conf(default = value)] |
Uses value |
Parsed with FromStr |
Option<T> |
None |
Some(parsed_value) |
T + #[conf(deserializer = "fn")] |
Error | Parsed with custom function |
Combining Attributes
Multiple attributes can be combined to create powerful configurations:
use ServiceConf;
Invalid combinations (compile errors):
Option<T>+#[conf(default)]or#[conf(default = value)]→ Option already defaults to None
Error Handling
The from_env() method returns a Result that can be handled appropriately:
use ServiceConf;
match from_env
Example error messages:
Environment variable 'DATABASE_URL' is required but not setFailed to parse environment variable 'PORT' as u16: invalid digit found in stringFailed to read file '/etc/secrets/key' for environment variable 'API_KEY_FILE': No such file or directory