Files
rustybeds/wiki/05-configuration.md
gramps 2a9afe7d77 Add MariaDB IPL validation, topology docs in beds.toml, and developer wiki
- 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>
2026-04-04 15:41:28 -07:00

171 lines
5.8 KiB
Markdown

# Configuration System
## Design Philosophy
BEDS configuration follows two rules:
1. **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.
2. **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:
```bash
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:
```toml
# 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
```toml
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
```toml
[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
```toml
[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:
```toml
[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`):
```toml
[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):
```toml
[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()`:
```rust
// 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
1. Add the TOML section to `beds.toml` with safe defaults and full commentary
2. Add the same section to `tests/fixtures/beds_test.toml` with test-safe values
3. Add the corresponding struct(s) to `src/config/structs.rs`
4. Export the new type from `src/config/mod.rs`
5. Add the field to `BedsConfig`
6. Update this wiki page