This guide explains Mostro’s boot sequence and configuration surfaces.
- Entry:
src/main.rs:1 - Initializes logging (RUST_LOG), settings, DB, Nostr client, LND connector, RPC (optional), scheduler.
- Resubscribes held invoices, then calls
app::run.
Before settings initialization, the daemon performs (see src/main.rs):
- Screen clearing: Clears terminal for clean output
- Logging setup:
let rust_log = if cfg!(debug_assertions) { "debug" } else { env::var("RUST_LOG").unwrap_or_else(|_| "info".to_string()) }; env::set_var("RUST_LOG", rust_log); pretty_env_logger::init();
- Debug/Release mode detection: Sets appropriate log level
Directory setup:
- Creates
~/.mostro/directory if not exists - Checks for existing
~/.mostro/settings.toml - If missing: copies
settings.tpl.tomlto~/.mostro/settings.toml - On first run after creating the file, the process exits so the user can edit
settings.toml, then restart Mostro. - Overrides database URL:
~/.mostro/mostro.dbSettings loading: - Parses TOML into Settings struct
- Stores in global
config::MOSTRO_CONFIGviainit_mostro_settings() - Accessible via
Settings::get_*()methods throughout application
Source: src/db.rs, function connect().
Initialization:
-
New database creation:
- Detects if database file exists
- If new: runs all migrations from
migrations/directory - Creates tables, indexes, and schema
-
Legacy migrations:
- Performs column migrations for backwards compatibility
- Example: disputes table structure updates
-
Connection pooling:
- Creates
SqlitePoolwith configured connection limits - Stores in global
config::DB_POOL
- Creates
Note: Database encryption has been removed; no password is used for the database.
Error handling: Database connection errors halt startup
- Settings init:
cli::settings_init()loadssettings.toml(template:settings.tpl.toml). - DB connect:
db::connect()setsconfig::DB_POOL. - Nostr:
util::connect_nostr()setsconfig::NOSTR_CLIENT. - NIP-01 Kind 0 Metadata: If any metadata fields (
name,about,picture,website) are configured, publishes a kind 0 metadata event so clients can display the Mostro instance's profile. - LND:
LndConnector::new()+get_node_info()→config::LN_STATUS. - Held invoices:
db::find_held_invoices()→ resubscribe viautil::invoice_subscribe. - RPC: start if
rpc.enabled. - AppContext: Build
AppContextwith pool, client, settings, message queue, and keys. - Scheduler:
scheduler::start_scheduler(ctx)— receivesAppContextfor dependency injection. - Event loop:
app::run(ctx, ln_client)— receivesAppContextinstead of individual dependencies.
File: src/config/settings.rs, types in src/config/types.rs.
Configuration is loaded from ~/.mostro/settings.toml (template: settings.tpl.toml). Values shown below come from the template and indicate the required keys that must exist in settings.toml. Some fields have Rust Default implementations; however, the daemon still expects these keys to be present in settings.toml. If a key relies on a Rust Default and is present but empty or omitted by tooling, the daemon falls back to the Rust Default value.
Database (src/config/types.rs:21-26):
url(String): Database connection URL (Mostro uses SQLite)- Example (relative to the process working directory):
"sqlite://mostro.db" - Example (absolute path; use a real path — do not use
~; SQLx does not expand tilde):"sqlite:///home/youruser/.mostro/mostro.db" - Default:
"sqlite://mostro.db"
- Example (relative to the process working directory):
Nostr (src/config/types.rs):
nsec_privkey(String): Mostro's Nostr private key in nsec format.- Can be overridden by the
MOSTRO_NSEC_PRIVKEYenvironment variable (env var takes precedence; whitespace-only values are ignored). - Mostro also auto-loads
<settings_dir>/.envat startup (e.g.~/.mostro/.env) so the variable can live in a separate file with restricted permissions. - Precedence: real env var >
<settings_dir>/.env>settings.toml.
- Can be overridden by the
relays(Vec): List of Nostr relay URLs for event broadcasting- Default:
['ws://localhost:7000'] - Note: At least one relay required
- Default:
Lightning (src/config/types.rs:27-46):
lnd_cert_file(String): Path to LND TLS certificatelnd_macaroon_file(String): Path to LND macaroon auth filelnd_grpc_host(String): LND gRPC endpoint URLinvoice_expiration_window(u32): Required invoice validity window in seconds (default: 3600)hold_invoice_cltv_delta(u32): Hold invoice CLTV delta in blocks (default: 144)hold_invoice_expiration_window(u32): Hold invoice expiration in seconds (default: 300)payment_attempts(u32): Max payment retry attempts (default: 3)payment_retries_interval(u32): Retry interval in seconds (default: 60)
Mostro (src/config/types.rs:76-108):
Fee Configuration:
fee(f64): Mostro trading fee percentage (default: 0)max_routing_fee(f64): Maximum routing fee percentage; 0.002 = 0.2% (default: 0.002)
Order Limits:
max_order_amount(u32): Maximum order amount in satoshis (default: 1000000)min_payment_amount(u32): Minimum payment amount in satoshis (default: 100)max_orders_per_response(u8): Maximum orders returned in single response (default: 10)
Expiration Settings:
expiration_hours(u32): Order expiration in hours (default: 24)max_expiration_days(u32): Maximum allowed expiration in days (default: 15)expiration_seconds(u32): Pending order expiration in seconds (default: 900)
Publishing Intervals:
publish_relays_interval(u32): Relay list event interval in seconds (default: 60)user_rates_sent_interval_seconds(u32): User rate events interval in seconds (default: 3600)publish_mostro_info_interval(u32): Mostro info publish interval in seconds (default: 300)
Network/API:
pow(u8): Proof-of-work difficulty requirement (default: 0)bitcoin_price_api_url(String): Bitcoin price API base URL (default:https://api.yadio.io)
Market Support:
fiat_currencies_accepted(Vec): Accepted fiat currencies; empty list accepts all (default: ['USD', 'EUR', 'ARS', 'CUP'])
NIP-01 Kind 0 Metadata (optional):
name(Option<String>): Human-readable name for this Mostro instance (default: None)about(Option<String>): Short description of this Mostro instance (default: None)picture(Option<String>): URL to avatar image, recommended square max 128x128px (default: None)website(Option<String>): Operator website URL (default: None)
RPC (src/config/types.rs:55-74):
enabled(bool): Enable RPC server (Rust Default: false)listen_address(String): Bind address (Rust Default: "127.0.0.1")port(u16): Listen port (Rust Default: 50051)- Note: These fields have a Rust Default implementation, but
settings.tomlmust still include these keys. If a key is present but empty or omitted by tooling, the daemon falls back to the Rust Default value.
Source: src/config/mod.rs
pub static MOSTRO_CONFIG: OnceLock<Settings> = OnceLock::new();
pub static NOSTR_CLIENT: OnceLock<Client> = OnceLock::new();
pub static LN_STATUS: OnceLock<LnStatus> = OnceLock::new();
pub static DB_POOL: OnceLock<Arc<sqlx::SqlitePool>> = OnceLock::new();
pub static MESSAGE_QUEUES: LazyLock<MessageQueues> =
LazyLock::new(MessageQueues::default);(MessageQueues holds Arc<RwLock<…>> queues for order messages, cant-do messages, rating events, and restore-session messages.)
There is no database password or separate global for SQLite; the daemon opens the file URL from [database] in settings.toml only.
Access patterns:
Settings::get_mostro()→ Mostro settingsSettings::get_ln()→ Lightning settingsSettings::get_rpc()→ RPC settings- Database:
config::DB_POOL.get().unwrap() - Nostr:
config::NOSTR_CLIENT.get().unwrap()
- Build:
cargo build - Run:
cargo run - SQLx offline data:
cargo sqlx prepare -- --bin mostrod
- Do not commit populated
settings.toml. - Keep templates in
settings.tpl.toml; place runtime config at~/.mostro/settings.toml.