- Add MariaDB (REL) IPL validation — master required, secondary non-fatal
- Add RelNodeConfig / RelInstanceConfig structs with master/secondary pattern
- Add rel_services section to beds.toml and test fixture
- Add detailed topology commentary to beds.toml covering standalone,
master/replica, Galera cluster, and multi-DB-per-node configurations
- Add developer wiki (wiki/) covering:
- Origin story — PHP Namaste history, production record, why Rust
- Architecture overview — full system diagram, all layers explained
- The four nodes — appServer, admin, segundo, tercero with real-world context
- IPL sequence — every step documented with rationale for ordering
- Configuration system — layering, env selection, adding new sections
- Queue topology — exchanges, routing keys, broker bindings, vhost isolation
- Template system — REC/REL, TLA convention, cache map, warehousing
- Event lineage — compound event IDs, parent/child tracking, msLogs schema
- Glossary
- Update README with wiki index and MariaDB status
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
5.8 KiB
Configuration System
Design Philosophy
BEDS configuration follows two rules:
-
The base file is always safe to commit. It contains structure and production-safe defaults. No real passwords, no real hostnames. It is the documentation of what the config looks like.
-
The env file is never committed. It contains the real values for a specific environment. It lives on the server and is gitignored. If the env file is lost, you rebuild it — you never recover it from git history.
This is the same pattern used in the PHP Namaste framework from day one. The namaste.xml base file was committed. The env.xml override was not. The habit was intentional: committing credentials to source control, even a private repo, is a category of mistake that ends careers.
File Locations
config/
├── beds.toml ← committed — base config, safe defaults
├── env_dev.toml ← gitignored — development overrides
├── env_qa.toml ← gitignored — QA / staging overrides
└── env_prod.toml ← gitignored — production overrides
Environment Selection
The BEDS_ENV environment variable selects which override file to load:
BEDS_ENV=dev cargo run # loads env_dev.toml (default if unset)
BEDS_ENV=qa ./rustybeds # loads env_qa.toml
BEDS_ENV=prod ./rustybeds # loads env_prod.toml
If BEDS_ENV is unset, dev is assumed. This means a freshly cloned repo with no env file runs in dev mode — which is the correct safe default.
How Layering Works
The config crate performs a deep merge. Only keys present in the env file override the base. Everything else inherits from beds.toml.
Example — overriding only the broker password and env name:
# env_dev.toml — only what differs from beds.toml
[id]
env_name = "development"
[broker_services.app_server]
pass = "my-dev-rabbitmq-password"
Every other value — host, port, vhost, instance counts — is inherited from beds.toml. You do not need to repeat the full config in the env file.
Configuration Sections
Root Flags
debug = false # debug-level log output
syslog = true # route logs to journald
syslog_mirror_console = true # also echo to console when syslog=true
audit_on = false # global auditing master switch
journal_on = false # global journaling master switch
[id] — Node Identity
[id]
env_name = "production" # development | qa | production
version = "1.0" # match your git release tag
wbid = "ms" # 2-char corporate identifier — prefixed to all collection names
The wbid is permanent. Once your MongoDB collections are created with a given wbid, changing it means renaming every collection and updating every template. Choose carefully.
[broker_services] — RabbitMQ
[broker_services]
queue_tag = "prod_" # prefixed to every queue name — isolates envs
vhost = "prod" # RabbitMQ virtual host
timer_violation = 3000 # ms before a broker round-trip is a slow query warning
records_per_xfer = 5000 # max records per broker response — circuit breaker
keepalive = true # TCP keepalive — always true in production
heartbeat = 60 # AMQP heartbeat interval in seconds
use_ssl = false # TLS for broker connections
cert_path = "/etc/rabbitmq"
Per-node broker config:
[broker_services.app_server]
host = "localhost"
port = 5672
api_port = 15672 # management UI
user = "beds"
pass = "changeme"
rpi = 50 # records per interval — broker fetch throttle
[broker_services.app_server.instances]
r_broker = 2 # read brokers
w_broker = 2 # write brokers
m_broker = 0 # migration brokers (0 = disabled)
[rec_services] — MongoDB
One entry per BEDS service role that needs MongoDB. Key is the service name (app_server, admin, segundo, tercero):
[rec_services.app_server]
host = "localhost"
port = 27017
user = "beds"
pass = "changeme"
database = "beds_app"
use_ssl = false
See beds.toml for topology examples (standalone, replica set, sharded cluster).
[rel_services] — MariaDB
One entry per service role, with master (required) and secondary (optional):
[rel_services.app_server.master]
host = "localhost"
port = 3306
user = "beds"
pass = "changeme"
database = "beds_app"
[rel_services.app_server.secondary] # optional read replica
host = "replica.internal"
port = 3306
user = "beds_readonly"
pass = "changeme"
database = "beds_app"
Secondary failure is always non-fatal — BEDS logs a warning and operates master-only.
The Test Fixture
All tests load from tests/fixtures/beds_test.toml instead of the live config. This file is committed — it contains only localhost addresses and placeholder credentials. Tests never read config/beds.toml.
The fixture is loaded via config::load_from():
// in unit tests (inside source files)
fn test_cfg() -> BedsConfig {
load_from("tests/fixtures/beds_test.toml", "")
.expect("test fixture failed to load")
}
// in integration tests (under tests/)
let cfg = common::load_test_config();
If a test needs a different value, mutate the loaded struct — do not create a separate fixture file for every test variation. The fixture is the baseline; tests modify what they need.
Adding a New Config Section
- Add the TOML section to
beds.tomlwith safe defaults and full commentary - Add the same section to
tests/fixtures/beds_test.tomlwith test-safe values - Add the corresponding struct(s) to
src/config/structs.rs - Export the new type from
src/config/mod.rs - Add the field to
BedsConfig - Update this wiki page