
Environment Variable Substitution
Muti Metroo configuration files support environment variable substitution, allowing you to externalize secrets and deployment-specific values.
Syntax
Basic Substitution
agent:
log_level: "${LOG_LEVEL}"
If LOG_LEVEL is not set, the agent will fail to start.
With Default Value
agent:
log_level: "${LOG_LEVEL:-info}"
Uses info if LOG_LEVEL is not set.
Examples
agent:
id: "${AGENT_ID:-auto}"
display_name: "${HOSTNAME:-unknown}"
data_dir: "${DATA_DIR:-./data}"
log_level: "${LOG_LEVEL:-info}"
socks5:
address: "${SOCKS_ADDR:-127.0.0.1:1080}"
auth:
users:
- username: "${SOCKS_USER:-user}"
password_hash: "${SOCKS_PASS_HASH}"
peers:
- id: "${PEER_ID}"
transport: "${PEER_TRANSPORT:-quic}"
address: "${PEER_ADDR}"
Common Use Cases
Secrets
Never hardcode secrets in configuration:
socks5:
auth:
users:
- username: "admin"
password_hash: "${SOCKS5_PASSWORD_HASH}"
rpc:
password_hash: "${RPC_PASSWORD_HASH}"
file_transfer:
password_hash: "${FILE_TRANSFER_PASSWORD_HASH}"
TLS Certificates
Inline certificates from environment:
listeners:
- transport: quic
tls:
cert_pem: "${TLS_CERT}"
key_pem: "${TLS_KEY}"
client_ca_pem: "${TLS_CA}"
Deployment Configuration
Different values per environment:
agent:
display_name: "${ENVIRONMENT:-dev}-${HOSTNAME}"
http:
address: "${HTTP_ADDR:-:8080}"
listeners:
- transport: quic
address: "${LISTEN_ADDR:-0.0.0.0:4433}"
Dynamic Peer Discovery
peers:
- id: "${PEER_1_ID}"
address: "${PEER_1_ADDR}"
transport: quic
tls:
ca: "${PEER_1_CA:-/etc/muti-metroo/ca.crt}"
- id: "${PEER_2_ID}"
address: "${PEER_2_ADDR}"
transport: quic
tls:
ca: "${PEER_2_CA:-/etc/muti-metroo/ca.crt}"
Running with Environment Variables
Command Line
# Single variable
LOG_LEVEL=debug muti-metroo run -c config.yaml
# Multiple variables
SOCKS_ADDR=0.0.0.0:1080 \
LOG_LEVEL=info \
PEER_ID=abc123 \
muti-metroo run -c config.yaml
Environment File
Create .env file:
# .env
LOG_LEVEL=info
SOCKS_ADDR=0.0.0.0:1080
SOCKS5_PASSWORD_HASH=$2a$10$...
PEER_ID=abc123def456789012345678901234ab
PEER_ADDR=192.168.1.10:4433
Load and run:
# Using env command
env $(cat .env | xargs) muti-metroo run -c config.yaml
# Using set -a
set -a && source .env && set +a
muti-metroo run -c config.yaml
Docker
docker run -d \
-e LOG_LEVEL=info \
-e SOCKS_ADDR=0.0.0.0:1080 \
-e PEER_ID=abc123... \
-v ./config.yaml:/app/config.yaml \
muti-metroo
Or with env file:
docker run -d \
--env-file .env \
-v ./config.yaml:/app/config.yaml \
muti-metroo
Docker Compose
services:
agent:
image: muti-metroo
environment:
- LOG_LEVEL=info
- SOCKS_ADDR=0.0.0.0:1080
env_file:
- .env
volumes:
- ./config.yaml:/app/config.yaml
Kubernetes
ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: muti-metroo-config
data:
LOG_LEVEL: "info"
SOCKS_ADDR: "0.0.0.0:1080"
Secret:
apiVersion: v1
kind: Secret
metadata:
name: muti-metroo-secrets
type: Opaque
stringData:
SOCKS5_PASSWORD_HASH: "$2a$10$..."
TLS_KEY: |
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
Deployment:
spec:
containers:
- name: muti-metroo
envFrom:
- configMapRef:
name: muti-metroo-config
- secretRef:
name: muti-metroo-secrets
systemd
# /etc/systemd/system/muti-metroo.service
[Service]
Environment="LOG_LEVEL=info"
Environment="SOCKS_ADDR=0.0.0.0:1080"
EnvironmentFile=/etc/muti-metroo/environment
ExecStart=/usr/local/bin/muti-metroo run -c /etc/muti-metroo/config.yaml
Best Practices
1. Use Defaults for Non-Secrets
# Good - has sensible default
log_level: "${LOG_LEVEL:-info}"
# Bad - will fail if not set
log_level: "${LOG_LEVEL}"
2. Never Default Secrets
# Good - forces explicit configuration
password_hash: "${PASSWORD_HASH}"
# Bad - insecure default
password_hash: "${PASSWORD_HASH:-$2a$10$defaulthash...}"
3. Document Required Variables
# Required environment variables:
# - PEER_ID: Agent ID of peer
# - PEER_ADDR: Address of peer
# - SOCKS5_PASSWORD_HASH: bcrypt hash for SOCKS5 auth
#
# Optional:
# - LOG_LEVEL: Logging level (default: info)
# - SOCKS_ADDR: SOCKS5 bind address (default: 127.0.0.1:1080)
4. Use Descriptive Names
# Good
MUTI_METROO_LOG_LEVEL
MUTI_METROO_SOCKS5_PASSWORD_HASH
# OK for simple deployments
LOG_LEVEL
SOCKS5_PASSWORD_HASH
5. Validate Before Deployment
# Check all required vars are set
required_vars="PEER_ID PEER_ADDR SOCKS5_PASSWORD_HASH"
for var in $required_vars; do
if [ -z "${!var}" ]; then
echo "Error: $var is not set"
exit 1
fi
done
Troubleshooting
Missing Environment Variable
Error: environment variable PEER_ID not set
Set the variable or add a default value.
Multiline Values
For multiline values (like PEM certificates):
# In shell
export TLS_CERT="$(cat ./certs/agent.crt)"
# In .env file (escape newlines)
TLS_CERT="-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----"
Special Characters
Escape special characters in values:
# Password with special chars
SOCKS5_PASSWORD_HASH='$2a$10$abc123...' # Use single quotes
Related
- Configuration Overview - Full configuration reference
- Deployment: Docker - Docker deployment
- Deployment: Kubernetes - Kubernetes deployment